In android, why is a singleton never recycled? - android

I'm confused on this. Just started android and have a long form that needs multiple activities to bring together an object. I would like to pass the object from activity to activity to build it. After reading the many posts and blogs and the Android Dev pages, it seems for non-persistent data, the best bet is to subclass application or create a singleton. I reviewed this post openFileOutput not working properly inside a singleton class - ideas/workarounds? and now my question is this, Why doesn't a singleton ever get recycled? If we createSingleton() in Activity A, then move to Activity B and we are never passing a reference to the singleton, how does the garbage recycler know that we are going to come back to it again? it seems to me that when Activity A is recycled and we have moved to Activity B that the singleton would die..
If we look at the following singleton..
public final class SomeSingleton implements Cloneable {
private static final String TAG = "SomeSingleton";
private static SomeSingleton someSingleton ;
private static Context mContext;
/**
* I'm private because I'm a singleton, call getInstance()
* #param context
*/
private SomeSingleton(){
// Empty
}
public static synchronized SomeSingleton getInstance(Context context){
if(someSingleton == null){
someSingleton = new SomeSingleton();
}
mContext = context.getApplicationContext();
return someSingleton;
}
public void playSomething(){
// Do whatever
mContext.openFileOutput("somefile", MODE_PRIVATE); // etc...
}
public Object clone() throws CloneNotSupportedException {
throw new CloneNotSupportedException("I'm a singleton!");
}
}
And we create an instance of it through getInstance(), the class places a single instance of the class into static field, someSingleton. Why is this instance never recycled? If the answer is, "Static fields are never recycled?" What keeps us from using up all of our memory if we have many of them? Simple design considerations? This seems risky if we are using lots of contributed libraries that we have no idea how many static fields are out there. I just have this feeling that there is some fundamental rule that I am missing in OOP as a newb.

The general pattern is to put a reference to your singleton class in a static field. Static fields are not tied to a particular instance so they stick around until the JVM process is alive. It doesn't really matter how many activities access it. If you need to 'recycle' the singleton, maye you don't really need to use a singleton? Or provide an explicit close()/open() etc. methods.

I think the reason that your Singleton's are not getting recycled is because activities in Android aren't destroyed when you think they are.
You pose a question like 'what happens when we move from activity A to B'. But when you do that in Android, Activity A is very rarely destroyed. It usually just goes into the onPause() state. Thus, your Activity A will still be (mostly) intact if and when a user decided to hit the back button enough times to get back to activity A.

Related

Saving a static Context variable in Application class

I've wondering if it's okay to do this: whenever we pass a Context variable around, could we just get a singleton reference from the Application class instead
For example here is a subclass of Application class with a single static variable pointing to its own instance
public class App extends Application {
public static mApp;
#Override
public void onCreate(){
mApp = this;
}
}
Then when we need to pass a Context to a method from somewhere, can we just do
foo(App.mApp);
Isn't it okay to treat Context as an application variable?
Well it depends on the context in which you are using it. Many times a context is meant to keep hold of things until it's lifescope is complete and then allow garbage collection to take back whatever it was owning.
Other times the context needs to be an activity to handle life cycle call backs such as onNewIntent or onActivityResult.
Keeping a static instance in the parent is just a shortcut to avoid having to getApplication() and cast it as your type of application. I typically make a method for MyApplication.getApplication().doSomething which will return it's own reference of itself as opposed to ((MyApplication)getApplication()).doSomething
Just seems cleaner for coding purposes. But I would be very leary of using the application context everywhere you need a context, it will come back to bite you eventually.
But yes you can certainly store yourself as a static variable to be shared, I do it in most applications, but typically for a specific shortcut purpose of clean maintainable code, not for cheating on getting context from various crevices.

Is it bad in terms of memory usage if I use static fields in activities and fragments?

I was wondering whether I should declare my fields static or not inside activities/fragments.
At first I thought I'd make everything static, since every fragment/activity would only have only one instance in memory at a time (is this correct?)
Then I read here at SO that fields marked as static would never be GC'ed, since only only objects (along with their instance variables) are garbage collected. I'm puzzled
Here's how I'm doing it now....
public class Container extends FragmentActivity implements ActionBar.TabListener {
private static ViewPager sPager;
private static ActionBar sActionBar;
private static PagerAdapter sAdapter;
private static DrawerLayout sDrawerLayout;
private static ListView sDrawerList;
private static ActionBarDrawerToggle sDrawerToggle;
//more code...
(I'm sorry if i'm mixing things up here, I'm new to programming...Also English isn't my first language)
Any answers are appreciated.
What is the impact of Static variable ?
Static variables serve as "roots" to the GC. Therefore, unless you explicitly set them to null, they will live as long as the program lives, and so is everything reachable from them.
So, if you declare a view as static what happens is, the reference created to the activity or fragment stays alive even after the activity is destroyed (may be due to change in device orientation) which creates a memory leak.
So should we never use Static ?
Answer is NO. YOU SHOULD USE STATIC CAUTIOUSLY
If a variable or data is intended to be there for as long as the program is running, then it is most definitely not a leak, it is more likely a "permanent singleton". If the OS tries to access a data and if the object is null, it is a bigger issue. So in those case, static is helpful.
If needed, How to handle the static variable ?
Any variable or view you declare as static, should be assigned null in the activity onDestroy Method or any other appropriate method.
Hope this helps.
The objects in your example are a bunch of views and an adapter. Views and adapters have a lifecycle that's tied to the activity that they're part of – if the activity is gone, then the views that it's made up of should also be gone.
Therefore, these objects should not be held in static fields (unless you null those fields in onDestroy(), but really, why bother).
You have a class Container, if you make these fields static, it means these are fields of the class and common for all objects/instances of this class.
You are right, for Activities you will probably only have one instance, but still these fields belong to this one instance, as Barend said in his response, and are not common with others.
Also your point with garbage collection is valid and an important point on mobile devices since resources are limited and memory leaks happen easily when static is not used carefully.
static: Use it if a field is shared between instances of the class and may even exist without any instance existing. If you are unsure, better don't use static.

Why extend the Android Application class?

An extended Application class can declare global variables. Are there other reasons?
Introduction:
If we consider an apk file in our mobile, it is comprised of
multiple useful blocks such as, Activitys, Services and
others.
These components do not communicate with each other regularly and
not forget they have their own life cycle. which indicate that
they may be active at one time and inactive the other moment.
Requirements:
Sometimes we may require a scenario where we need to access a
variable and its states across the entire Application regardless of
the Activity the user is using,
An example is that a user might need to access a variable that holds his
personnel information (e.g. name) that has to be accessed across the
Application,
We can use SQLite but creating a Cursor and closing it again and
again is not good on performance,
We could use Intents to pass the data but it's clumsy and activity
itself may not exist at a certain scenario depending on the memory-availability.
Uses of Application Class:
Access to variables across the Application,
You can use the Application to start certain things like analytics
etc. since the application class is started before Activitys or
Servicess are being run,
There is an overridden method called onConfigurationChanged() that is
triggered when the application configuration is changed (horizontal
to vertical & vice-versa),
There is also an event called onLowMemory() that is triggered when
the Android device is low on memory.
Application class is the object that has the full lifecycle of your application. It is your highest layer as an application. example possible usages:
You can add what you need when the application is started by overriding onCreate in the Application class.
store global variables that jump from Activity to Activity. Like Asynctask.
etc
Sometimes you want to store data, like global variables which need to be accessed from multiple Activities - sometimes everywhere within the application. In this case, the Application object will help you.
For example, if you want to get the basic authentication data for each http request, you can implement the methods for authentication data in the application object.
After this,you can get the username and password in any of the activities like this:
MyApplication mApplication = (MyApplication)getApplicationContext();
String username = mApplication.getUsername();
String password = mApplication.getPassword();
And finally, do remember to use the Application object as a singleton object:
public class MyApplication extends Application {
private static MyApplication singleton;
public MyApplication getInstance(){
return singleton;
}
#Override
public void onCreate() {
super.onCreate();
singleton = this;
}
}
For more information, please Click Application Class
Offhand, I can't think of a real scenario in which extending Application is either preferable to another approach or necessary to accomplish something. If you have an expensive, frequently used object you can initialize it in an IntentService when you detect that the object isn't currently present. Application itself runs on the UI thread, while IntentService runs on its own thread.
I prefer to pass data from Activity to Activity with explicit Intents, or use SharedPreferences. There are also ways to pass data from a Fragment to its parent Activity using interfaces.
The Application class is a singleton that you can access from any activity or anywhere else you have a Context object.
You also get a little bit of lifecycle.
You could use the Application's onCreate method to instantiate expensive, but frequently used objects like an analytics helper. Then you can access and use those objects everywhere.
Best use of application class.
Example: Suppose you need to restart your alarm manager on boot completed.
public class BaseJuiceApplication extends Application implements BootListener {
public static BaseJuiceApplication instance = null;
public static Context getInstance() {
if (null == instance) {
instance = new BaseJuiceApplication();
}
return instance;
}
#Override
public void onCreate() {
super.onCreate();
}
#Override
public void onBootCompleted(Context context, Intent intent) {
new PushService().scheduleService(getInstance());
//startToNotify(context);
}
Not an answer but an observation: keep in mind that the data in the extended application object should not be tied to an instance of an activity, as it is possible that you have two instances of the same activity running at the same time (one in the foreground and one not being visible).
For example, you start your activity normally through the launcher, then "minimize" it. You then start another app (ie Tasker) which starts another instance of your activitiy, for example in order to create a shortcut, because your app supports android.intent.action.CREATE_SHORTCUT. If the shortcut is then created and this shortcut-creating invocation of the activity modified the data the application object, then the activity running in the background will start to use this modified application object once it is brought back to the foreground.
I see that this question is missing an answer. I extend Application because I use Bill Pugh Singleton implementation (see reference) and some of my singletons need context. The Application class looks like this:
public class MyApplication extends Application {
private static final String TAG = MyApplication.class.getSimpleName();
private static MyApplication sInstance;
#Contract(pure = true)
#Nullable
public static Context getAppContext() {
return sInstance;
}
#Override
public void onCreate() {
super.onCreate();
Log.d(TAG, "onCreate() called");
sInstance = this;
}
}
And the singletons look like this:
public class DataManager {
private static final String TAG = DataManager.class.getSimpleName();
#Contract(pure = true)
public static DataManager getInstance() {
return InstanceHolder.INSTANCE;
}
private DataManager() {
doStuffRequiringContext(MyApplication.getAppContext());
}
private static final class InstanceHolder {
#SuppressLint("StaticFieldLeak")
private static final DataManager INSTANCE = new DataManager();
}
}
This way I don't need to have a context every time I'm using a singleton and get lazy synchronized initialization with minimal amount of code.
Tip: updating Android Studio singleton template saves a lot of time.
I think you can use the Application class for many things, but they are all tied to your need to do some stuff BEFORE any of your Activities or Services are started.
For instance, in my application I use custom fonts. Instead of calling
Typeface.createFromAsset()
from every Activity to get references for my fonts from the Assets folder (this is bad because it will result in memory leak as you are keeping a reference to assets every time you call that method), I do this from the onCreate() method in my Application class:
private App appInstance;
Typeface quickSandRegular;
...
public void onCreate() {
super.onCreate();
appInstance = this;
quicksandRegular = Typeface.createFromAsset(getApplicationContext().getAssets(),
"fonts/Quicksand-Regular.otf");
...
}
Now, I also have a method defined like this:
public static App getAppInstance() {
return appInstance;
}
and this:
public Typeface getQuickSandRegular() {
return quicksandRegular;
}
So, from anywhere in my application, all I have to do is:
App.getAppInstance().getQuickSandRegular()
Another use for the Application class for me is to check if the device is connected to the Internet BEFORE activities and services that require a connection actually start and take necessary action.
Source: https://github.com/codepath/android_guides/wiki/Understanding-the-Android-Application-Class
In many apps, there's no need to work with an application class directly. However, there are a few acceptable uses of a custom application class:
Specialized tasks that need to run before the creation of your first activity
Global initialization that needs to be shared across all components (crash reporting, persistence)
Static methods for easy access to static immutable data such as a shared network client object
You should never store mutable instance data inside the Application object because if you assume that your data will stay there, your application will inevitably crash at some point with a NullPointerException. The application object is not guaranteed to stay in memory forever, it will get killed. Contrary to popular belief, the app won’t be restarted from scratch. Android will create a new Application object and start the activity where the user was before to give the illusion that the application was never killed in the first place.
To add onto the other answers that state that you might wish store variables in the application scope, for any long-running threads or other objects that need binding to your application where you are NOT using an activity (application is not an activity).. such as not being able to request a binded service.. then binding to the application instance is preferred. The only obvious warning with this approach is that the objects live for as long as the application is alive, so more implicit control over memory is required else you'll encounter memory-related problems like leaks.
Something else you may find useful is that in the order of operations, the application starts first before any activities. In this timeframe, you can prepare any necessary housekeeping that would occur before your first activity if you so desired.
2018-10-19 11:31:55.246 8643-8643/: application created
2018-10-19 11:31:55.630 8643-8643/: activity created
You can access variables to any class without creating objects, if its extended by Application. They can be called globally and their state is maintained till application is not killed.
The use of extending application just make your application sure for any kind of operation that you want throughout your application running period. Now it may be any kind of variables and suppose if you want to fetch some data from server then you can put your asynctask in application so it will fetch each time and continuously, so that you will get a updated data automatically.. Use this link for more knowledge....
http://www.intridea.com/blog/2011/5/24/how-to-use-application-object-of-android

Application class lifecycle while service is running

I am developing an application with custom Application class which initializes a couple of singletons so they live during all application working time. I also have a couple of services in my application which work with these singletons. Is it possible situation that Application class will be destroyed by android with singletons' instances before services so services will not be able to use them? Or application lives always even for services of it's context? What is the best way to find a way out of this situation?
Thanks.
Regarding the application object:
The application object is the main absolute starting point on any Android app. It will always exist before any of the Manifest declared items such as Activity, Service and BroadcastReceiver. So relax that the singletons will be there for you.
Regarding the singleton paradigma:
That's a big discussion topic, you can google more about it so what follows is my personal opinion on it. Whatever is the reason for your singletons (a database, an bitmap caching, a FileUtils) I think it's ok and correct to initialise them on the very first point of entry of your app, which is the Application. But the application itself is not an object meant to carry or hold those objects, that way my suggested design approach is to:
=> on your singleton object/class you'll have to:
private static MySingletonClass instance; // reference to the single object
private MySingletonClass(Context c){ // private constructor to avoid construction from anywhere else
// let's say it needs the context for construction because it's a database singleton
}
public static MySingletonClass get(){ //
if(instance == null) throw new RuntimeException("This singleton must be initialised before anything else");
return instance;
}
public static void init(Context c){ // call the initialisation from the Application
instance = new MySingletonClass(c);
}
=> and then on your Application object you simply init the singleton
onCreate(){
MySingletonClass.init(getApplicationContext());
}
with that way you'll keep the necessary initialisation, enforce the singleton pattern but to access the object you call to that object class not to the application. I know it's just a organisational difference, but I believe that that's what separate good and bad code.
So for example on your service the call is: MySingletonClass.get() and should never be MyApplication.mySingle.
hope it helps.
From my understanding service can't live without application context, service is bound to the application with the Context reference so I think if the application is killed also the Context is killed and that lead that all components are been killed,
you can read here for more info
http://developer.android.com/guide/components/fundamentals.html#proclife

Android Null Pointer Exception Madness?

So I have 3 Activities that need to all have access to the same custom class object (let's call it 'a') created by me when the very first Activity is created.
Because 'a' is made up of a whole bunch of non-primitives, I found it difficult to make Serializable or Parcelable. Instead I created a Service that binds to each Activity as they take the forefront, and gives the Activity 'a' in OnBind().
Now 'a' has a getter that gets another object of a different custom class stored with the same object (let's call it 'b'). In all three Activities, I also need to be able to access 'b'.
If I start the first Activity, use a button to navigate to the second Activity, press the "home" button on my phone, then go back into the application by pressing its icon, then navigate to the third activity by pressing a button, I get a null pointer exception on 'b' but not 'a'.
However if I add a line that prints 'a's getter for 'b' with sysout in the step where I press a button to get from the second Activity to the third, then there is no null pointer exception.
Does anybody know why this is and how I can resolve the issue?
Seems you want this object a to always be there!
I suggest extending application
public class YourApplication extends Application {
YourObject A;
#Override
public void onCreate(){
A = new YourObject();
}
//add getters or setters //
}
Now in your Activities:
YourApplication app;
app = app = ((YourApplication)getApplicationContext());
Finally in your Mainfest: Add to <application>
android:name=".YourApplication"
Sounds like you may want to consider a singleton class. An example (and description) in Java is here, but it boils down to:
public class ClassicSingleton {
private static ClassicSingleton instance = null;
protected ClassicSingleton() {
// Exists only to defeat instantiation.
}
public static ClassicSingleton getInstance() {
if(instance == null) {
instance = new ClassicSingleton();
}
return instance;
}
}
Now, when you want to access the singleton object, just use:
ClassicSingleton instance = ClassicSingleton.getInstance();
Sherif's solution would also work (and I was going to suggest this first, myself), but I prefer the singleton route as it's a little cleaner from an OO perspective.
Singletons have (at least) the following benefits over a global object:
Singletons use lazy instantiation so they are only created when they are first accessed, not when defined. If your object is costly to instantiate or maintain, it may be better to use a singleton rather than having it around for the life of the app
You can guarantee there will always be only one instance of a singleton - a global object can have as many instances as you have resources for

Categories

Resources