Singletons vs. Application Context in Android? - java

Recalling this post enumerating several problems of using singletons
and having seen several examples of Android applications using singleton pattern, I wonder if it's a good idea to use Singletons instead of single instances shared through global application state (subclassing android.os.Application and obtaining it through context.getApplication()).
What advantages/drawbacks would both mechanisms have?
To be honest, I expect the same answer in this post Singleton pattern with Web application, Not a good idea! but applied to Android. Am I correct? What's different in DalvikVM otherwise?
EDIT: I would like to have opinions on several aspects involved:
Synchronization
Reusability
Testing

I very much disagree with Dianne Hackborn's response. We are bit by bit removing all singletons from our project in favor of lightweight, task scoped objects which can easiliy be re-created when you actually need them.
Singletons are a nightmare for testing and, if lazily initialized, will introduce "state indeterminism" with subtle side effects (which may suddenly surface when moving calls to getInstance() from one scope to another). Visibility has been mentioned as another problem, and since singletons imply "global" (= random) access to shared state, subtle bugs may arise when not properly synchronized in concurrent applications.
I consider it an anti-pattern, it's a bad object-oriented style that essentially amounts to maintaining global state.
To come back to your question:
Although the app context can be considered a singleton itself, it is framework-managed and has a well defined life-cycle, scope, and access path. Hence I believe that if you do need to manage app-global state, it should go here, nowhere else. For anything else, rethink if you really need a singleton object, or if it would also be possible to rewrite your singleton class to instead instantiate small, short-lived objects that perform the task at hand.

I very much recommend singletons. If you have a singleton that needs a context, have:
MySingleton.getInstance(Context c) {
//
// ... needing to create ...
sInstance = new MySingleton(c.getApplicationContext());
}
I prefer singletons over Application because it helps keep an app much more organized and modular -- instead of having one place where all of your global state across the app needs to be maintained, each separate piece can take care of itself. Also the fact that singletons lazily initialize (at request) instead of leading you down the path of doing all initialization up-front in Application.onCreate() is good.
There is nothing intrinsically wrong with using singletons. Just use them correctly, when it makes sense. The Android framework actually has a lot of them, for it to maintain per-process caches of loaded resources and other such things.
Also for simple applications multithreading doesn't become an issue with singletons, because by design all standard callbacks to the app are dispatched on the main thread of the process so you won't have multi-threading happening unless you introduce it explicitly through threads or implicitly by publishing a content provider or service IBinder to other processes.
Just be thoughtful about what you are doing. :)

From: Developer > reference - Application
There is normally no need to subclass Application. In most situation,
static singletons can provide the same functionality in a more modular
way. If your singleton needs a global context (for example to register
broadcast receivers), the function to retrieve it can be given a
Context which internally uses Context.getApplicationContext() when
first constructing the singleton.

Application is not the same as the Singleton.The reasons are:
Application's method(such as onCreate) is called in the ui thread;
singleton's method can be called in any thread;
In the method "onCreate" of Application,you can instantiate Handler;
If the singleton is executed in none-ui thread,you could not
instantiate Handler;
Application has the ability to manage the life cycle of the
activities in the app.It has the method
"registerActivityLifecycleCallbacks".But the singletons has not the
ability.

I had the same problem: Singleton or make a subclass android.os.Application?
First I tried with the Singleton but my app at some point makes a call to the browser
Intent myIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.google.com"));
and the problem is that, if the handset doesn't have enough memory, most of your classes (even Singletons) are cleaned to get some memory so, when returning from the browser to my app, it crashed everytime.
Solution: put needed data inside a subclass of Application class.

Consider both at the same time:
having singleton objects as static instances inside the classes.
having a common class (Context) that returns the singleton instances for all the singelton objects in your application, which has the advantage that the method names in Context will be meaningful for example: context.getLoggedinUser() instead of User.getInstance().
Furthermore, I suggest that you expand your Context to include not only access to singleton objects but some functionalities that need to be accessed globally, like for example: context.logOffUser(), context.readSavedData(), etc. Probably renaming the Context to Facade would make sense then.

They're actually the same.
There's one difference I can see. With Application class you can initialize your variables in Application.onCreate() and destroy them in Application.onTerminate(). With singleton you have to rely VM initializing and destroying statics.

From the proverbial horse's mouth...
When developing your app, you may find it necessary to share data, context or services globally across your app. For example, if your app has session data, such as the currently logged-in user, you will likely want to expose this information. In Android, the pattern for solving this problem is to have your android.app.Application instance own all global data, and then treat your Application instance as a singleton with static accessors to the various data and services.
When writing an Android app, you're guaranteed to only have one instance of the android.app.Application class, and so it's safe (and recommended by Google Android team) to treat it as a singleton. That is, you can safely add a static getInstance() method to your Application implementation. Like so:
public class AndroidApplication extends Application {
private static AndroidApplication sInstance;
public static AndroidApplication getInstance(){
return sInstance;
}
#Override
public void onCreate() {
super.onCreate();
sInstance = this;
}
}

My 2 cents:
I did notice that some singleton / static fields were reseted when my activity was destroyed. I noticed this on some low end 2.3 devices.
My case was very simple : I just have a private filed "init_done" and a static method "init" that I called from activity.onCreate(). I notice that the method init was re-executing itself on some re-creation of the activity.
While I cannot prove my affirmation, It may be related to WHEN the singleton/class was created/used first. When the activity get destroyed/recycled, it seem that all class that only this activity refer are recycled too.
I moved my instance of singleton to a sub class of Application. I acces them from the application instance. and, since then, did not notice the problem again.
I hope this can help someone.

My activity calls finish() (which doesn't make it finish immediately, but will do eventually) and calls Google Street Viewer. When I debug it on Eclipse, my connection to the app breaks when Street Viewer is called, which I understand as the (whole) application being closed, supposedly to free up memory (as a single activity being finished shouldn't cause this behavior). Nevertheless, I'm able to save state in a Bundle via onSaveInstanceState() and restore it in the onCreate() method of the next activity in the stack. Either by using a static singleton or subclassing Application I face the application closing and losing state (unless I save it in a Bundle). So from my experience they are the same with regards to state preservation. I noticed that the connection is lost in Android 4.1.2 and 4.2.2 but not on 4.0.7 or 3.2.4, which in my understanding suggests that the memory recovery mechanism has changed at some point.

Related

Are static members in XPosed hook classes shared between processes?

I'm newer to Java, here's what I think XPosed works:
Before zygote_init, hook all apis and insert xposed_before_xxx and xposed_after_xxx method (where xxx is the name of the api).
Load modules. Load hook class, realize it and keep it in memory of zygote. For each injecting method, add it to the private list of xposed_before/after_xxx.
When an new app loads (forks from zygote), it also forked the hook class and the hooked method.
When an app calls xxx, it actually runs xposed_before_xxx first, and the latter calls every inject method in its private list. Then the original api is called. Then xposed_after_xxx is called, and deals with itself's list.
So for each app, hook class is individual after forking from zygote. So, static members are not shared. Cause each hook class has only one instance in an app, static members act the same as non-static members. Am I right?
Thanks for reading my long & poor English...
No, static members are not shared across processes. They act as static members within the app, not across apps.
Each application runs on its own VM so nothing is shared across processes.
Same applies for Xposed hooks, you can have a static method hooked for one application and not for others.
Even if you set your module to apply hooks on all applications, these hooks will be different instances in separate VMs.

Android Networking Class

I currently have an app that requires connection to a server in multiple activities. I am currently trying to create a class that handles the connection between multiple activities and provides getters to get the output streams, I have looked at a service class but I do not need to keep the connection when the app is not running.
I am not entirely sure what i need to do to get an object to be globally accessed from multiple activities without having to be instantiated the object in each activity.
A Service is still the best idea. You just have to make it keep track of how many Applications are connected to it (in onBind/onStartCommand/onUnbind), and make it shutdown when it goes to zero.
What is a bit tricky is that Applications are not really closed in Android when they don't have focus: you would have to decide if an Application unbinds from the Service on onPause or onStop.
You have 2 choices:
Make a singleton class. (I bet there is a lot of example in Google.)
Implement an "application" class.
http://developer.android.com/reference/android/app/Application.html
The differences:
For (1) it will instantiate the first time you access it. (But depending on design). For (2) it will instantiate together with the app process.
For (1) it is more complex to handle the object life cycle. For (2) you can manage your objects life cycle easily by controlling the access to the object in application.

With default bean scope as singleton, isn't it going to be bad when concurrent calls occur?

I have declared a Spring bean, which polls my email server every so and so seconds. If there is mail, it fetches it, and tries to extract any attached files in it. These files are then submitted to an Uploader which stores them safely. The uploader is also declared as a Spring bean. A third bean associates the email's sender with the file's filename and stores that in a DB.
It turned out that when a few people tried to send emails at the same time, a bunch of messy stuff happened. Records in the DB got wrong filenames. Some did not get filenames at all, etc.
I attributed the problem to the fact that beans are scoped to singleton by default. This means that a bunch of threads are probably messing up with one and the same instance at the same time. The question is how to solve this.
If I synchronize all the sensitive methods, then all threads will stack up and wait for each other, which is kind of against the whole idea of multithreading.
On the other hand, scoping the beans to "request" is going to create new instances of each of them, which is not really good either, if we speak about memory consumption, and thread scheduling
I am confused. What should I do?
Singleton-scoped beans should not hold any state - that solves the problem usually. If you only pass data as method parameters, and don't assign it to fields, you will be safe.
I agree with both #Bozho and #stivio answers.
The preferred options are to either pass store no state in a singleton scoped beans, and pass in a context object to the methods, or to use a prototype / request scoped beans that get created for every processing cycle. Synchronization can be usually avoided, by choosing one of these approaches, and you gain much more performance, while avoiding deadlocks. Just make sure you're not modifying any shared state, like static members.
There are pros and cons for each approach:
Singlton beans are act as a service-like class, which some may say are not a good Object-Oriented design.
Passing context to methods in a long chain of methods may make your code messy, if you're not careful.
Prototype beans may hold a lot of memory for longer than you intended, and may cause memory exhaustion. You need to be careful with the life cycle of these beans.
Prototype beans may make your design neater. Make sure you're not reusing beans by multiple threads though.
I tend to go with the service approach in most simple cases. You can also let these singleton beans create a processing object that can hold it's state for the computation. This is a solution that may serve you best for the more complexed scenarios.
Edit:
There are cases when you have a singleton bean depending on prototype scoped bean, and you want a new instance of the prototype bean for each method invocation. Spring supplies several solutions for that:
The first is using Method Injection, as described in the Spring reference documentation. I don't really like this approach, as it forces your class to be abstract.
The second is to use a ServiceLocatorFactoryBean, or your own factory class (which needs to be injected with the dependencies, and invoke a constructor). This approach works really well in most cases, and does not couple you to Spring.
There are cases when you also want the prototype beans to have runtime dependencies. A good friend of mine wrote a good post about this here: http://techo-ecco.com/blog/spring-prototype-scoped-beans-and-dependency-injection/.
Otherwise just declare your beans as request, don't worry about the memory consumption, the garbage collection will clear it up, as long there is enough memory it won't be a performance problem too.
Speaking abstractly: if you'e using Spring Integration, then you should build your code in terms of the messages themselves. Eg, all important state should be propagated with the messages. This makes it trivial to scale out by adding more spring Integration instances to handle the load. The only state (really) in Spring Integration is for components like the aggregator, which waits and collects messages that have a correllation. In this case, you can delegate to a backing store like MongoDB to handle the storage of these messages, and that is of course thread safe.
More generally, this is an example of a staged event driven architecture - components must statelessly (N(1) no matter how many messages) handle messages and then forward them on a channel for consumption by another component that does not know about the previous component from which the message came.
If you are encountering thread-safety issues using Spring Integration, you might be doing something a bit differently than intended and it might be worth revisiting your approach...
Singletons should be stateful and thread-safe.
If a singleton is stateless, it's a degenerate case of being stateful, and thread-safe is trivially true. But then what's the point of being singleton? Just create a new one everytime someone requests.
If an instance is stateful and not thread-safe, then it must not be singleton; each thread should exclusively have a different instance.

Is it safe to keep a reference to a thread in a singleton?

Let me give you the scenario.
Say that my first Activity that loads up, also creates a thread, which will run indefinitely in the background.
Now, if I move to another Activity, I assume that the thread that I initially created in the main activity will continue to run.
So, now to my main question - in order to manage this background thread from other Activities, is it safe to store a reference to that thread in a singleton object?
Yes and no. Theoretically, you will have no problem, but you must not allow references to escape.
Problems can arise from keeping the reference in the singleton object private, it must not pass the reference to anything else or allow access to it by anything else, or it can lose control.
Secondly, the thread created by your activity must not allow access to its member variables or allow references to them to escape.
A good book on this area is "Java Concurrency in Practice" by Brian Goetz
Actually where you need to be careful is if you have multiple class loaders. A Singleton is only a singleton if you are using the same class loader to load the class in. If you have multiple class loaders in your app running the same classes you will have another instance of the singleton in each.
Most standalone apps only use one classloader and therefore do not have any issues. If you have only one classloader then you will be fine.

How can I identify in which Java Applet context running without passing an ID?

I'm part of a team that develops a pretty big Swing Java Applet. Most of our code are legacy and there are tons of singleton references. We've bunched all of them to a single "Application Context" singleton. What we now need is to create some way to separate the shared context (shared across all applets currently showing) and non-shared context (specific to each applet currently showing).
However, we don't have an ID at each of the locations that call to the singleton, nor do we want to propagate the ID to all locations. What's the easiest way to identify in which applet context we're running? (I've tried messing with classloaders, thread groups, thread ids... so far I could find nothing that will enable me to ID the origin of the call).
Singletons are evil, what do you expect? ;)
Perhaps the most comprehensive approach would be to load the bulk of the applet in a different class loader (use java.net.URLClassLoader.newInstance). Then use a WeakHashMap to associate class loader with an applet. If you could split most of the code into a common class loader (as a parent of each per-applet class loader) and into the normal applet codebase, that would be faster but more work.
Other hacks:
If you have access to any component, you can use Component.getParent repeatedly or SwingUtilities.getRoot.
If you are in a per-applet instance thread, then you can set up a ThreadLocal.
From the EDT, you can read the current event from the queue (java.awt.EventQueue.getCurrentEvent()), and possibly find a component from that. Alternatively push an EventQueue with a overridden dispatchEvent method.
If I understand you correctly, the idea is to get a different "singleton" object for each caller object or "context".
One thing you can do is to create a thread-local global variable where you write the ID of the current context. (This can be done with AOP.) Then in the singleton getter, the context ID is fetched from the thread-local to use as a key to the correct "singleton" instance for the calling context.
Regarding AOP there should be no problem using it in applets since, depending on your point-cuts, the advices are woven at compile time and a JAR is added to the runtime dependencies. Hence, no special evidence of AOP should remain at run time.
#Hugo regarding threadlocal:
I thought about that solution. However, from experiments I found two problems with that approach:
Shared thread (server connections, etc) are problematic. This can be solved though by paying special attention to these thread (they're all under my control and are pretty much isolated from the legacy code).
The EDT thread is shared across all applets. I failed to find a way to force the creation of a new EDT thread for each applet. This means that the threadlocal for the EDT would be shared across the applets. This one I have no idea how to solve. Suggestions?

Categories