Say that I have a singleton class (Downloader) responsible for downloading and persisting files. When a client requests a download, he must also provide a callback. My question regards the storage of those callback objects.
If I have an Activity that implements the callback interface and then requests multiple large downloads, the Downloader class will hold a reference to the Activity indefinitely. What if before the downloads are finished the Activity that requested them goes through its life-cycle and is destroyed.
In this case the Downloader will prevent the recycler from garbage collecting the Activity. I don't mind that the requested downloads continue. What I would like to do however, is somehow detect that the callback provided should be collected and I am effectively leaking it.
Is there a design pattern for something like this? I was thinking that one of the Reference subclasses would be useful.
Thanks.
Do it the other way around and you can keep them disconnected and avoid the highly unrecommended practice of keeping activity references around.
I created a very simple ServiceLocator class that keeps static references to all of my singletons and resolves them by type, but you can do this even simpler. You just need a class that holds a static reference to your Downloader and exposes that reference to your activities. If you need to call back into any of your activities, use the publish/subscribe model that the Android framework does (i.e. setOnClickListener(OnClickListener listener)).
Downloader can have an inner interface called DownloadUpdateListener, a single instance of this interface, and a register and unregister method for setting this and removing the reference from your activities. The Activity will create an instance of it DownloadUpdateListener locally so it has access to all of the Activity's fields and views. In Downloader, check that your listener isn't null before calling its methods. Register your listener in onResume and don't forget to unregister it in onPause
Related
I have old Android/java code, that contains two derives from IntentService,
and these services not run in separate processes.
The question is about the way to return result from these IntentService.
One service return result by using Handler + Runnable, to run code in main loop:
new Handler(Looper.getMainLooper()).post(new Runnable() {
#Override
public void run() {
MyApplication.get().setFoo(someThing);
}
});
the other one is uses LocalBroadcastManager.getInstance(this).sendBroadcast(in); to send message to Activity, and Activity subscribe via BroadcastReceiver on message in onResume, and unsubscribe in onPause.
Am I right, and in both case it is possible to use LiveData to simplify things?
IntentService should create LiveData and who want result should observe it,
and when new data arrives IntentService should call postValue,
or may be there are some reefs to prevent usage of LiveData here?
I think that LiveData will not help you in sending any data from Service to other components.
The problem with communication from any Service to other components is that you don't usually obtain a direct reference to the Service, therefore you can't directly "subscribe" to notifications.
Theoretically, if the Service runs in the same process, you can bind it, obtain a reference to Service object and then directly perform subscription. However, this is often an overkill and I don't see this pattern being used widely.
In your examples, there are two communication mechanisms:
Service reaches statically to Application object and sets some data. This is a communication through global state, and is generally considered an anti-pattern.
Communication through LocalBroadcastManager
From the above two mechanisms, I would use only #2 and avoid #1 at all costs.
Back to LiveData.
In order to be able to get LiveData object from the Service you will need to have a reference to that Service. This is usually impossible unless you bind Service in the same process, or use some ugly hack that involves global state.
Therefore, usefulness of LiveData in this context is very limited.
By the way, while LocalBroadcastManager is alright, I find this mechanism too complicated and restricting. Therefore, if the Service runs in the same process, I prefer to use EventBus in order to communicate from Service to other components (or vice-versa).
An example of such a communication you can see in SQLite benchmarking application that I wrote several days ago. In this app, TestService posts status changes and test results to EventBus as sticky events, and TestActivity subscribes to those events.
Both methods work with using LiveData since the purpose of LiveData is to have it on another thread and still notify users when something has changed. Seems like it would definitely replace LocalBroadcastManager.getInstance(this).sendBroadcast(in); and your IntentService would postValue. Just have your activity or anything that needs to be aware of the changes become an observer.
In OO I think it is not uncommon for an object to register itself with another object (perhaps a singleton) for callbacks.
In C++ I think it is not uncommon to do this registration in the constructor or super class constructor of the object being registered and to do the deregistration its the destructor. This gives some assurances for the right timing.
I have two questions. What is the best strategy to achieve this in Java in general, given the lack of a destructor? In android, if the object is just a member of an activity or a fragment, I guess the object should be registered and deregistered from within two of the on... methods in the activity or the fragment. I think it may be hard to know exactly when the object will be destroyed. Which 2 on... methods in an activity or in a fragment would be best to use for this?
Additionally, perhaps less common, if the object is referenced from a number of other objects can one decide to deregister on the basis it is going out of scope and how or can one only deregister it based on some other state that just implies you are on balance probably happy to no longer receive call backs?
I am new to Android and I have a kind of design question. So I understand that it is recommended to use Fragments. I also understand that an Activity "owns" a Fragment.
So my question is the following:
Assume we want to make a long running background call e.g. HTTP to a server.
The results should be displayed in the UI.
So what is the best/standard practice?
1) Should the object doing the long running calls be "owned" by the Activity and the results send back to the Activity and then from the Activity to the Fragment so that the UI is updated?
2) Or should the object doing the long running called be "owned" by the Fragment and the results are send back to the Fragment for the UI to be updated? So the Activity is completely unaware of this?
Neither, IMHO. The object doing the long running should be managed by a Service, where you are using WakeLock (and, if needed, WifiLock) while the long-running HTTP operation is running. An IntentService might be a good candidate, as you need a background thread anyway.
The service, in turn, can use some sort of in-process event bus (LocalBroadcastManager, greenrobot's EventBus, Square's Otto, etc.), to let the UI layer know about any significant events that occurred from that HTTP operation. Whether the activity or the fragment is the one to subscribe to the events on the bus depends on what needs to happen for the event. If a fragment's widgets need to be updated, the fragment would subscribe. If the mix of fragments change, or some other activity-level UI change is needed, the activity would subscribe.
All of this assumes that by "long running" you mean something taking over a second or so.
For the long running task it's recommended to implement a sticky Service that contains a thread for the ServerSocket listener. Next I'd recommend to process requests by dedicated Thread's which are managed by a thread pool (check for instance this example).
In order to display results in your activity there are several approaches possible:
send a local broadcast from your service or thread which gets processed by registered BroadcastReceiver's which are part of your UI component (either Fragment's or Activity's)
bind your Service to the Activity (which might contain further fragments) and propagate information to containing fragments. There are three ways to go.
Note: In this post it's being said it's better to bind to the Application
pass data via Intent or a SQLiteDatabase
What I like and prefer is using local BroadcastReceiver's but this is just my personal preference.
It depends on your requirements, what might be the best solution.
I'm using a variation of the design recommended by #CommonsWare. I have an ApiClient class that listens to the event bus for requests to invoke API methods asynchronously. Any parameters that are needed for the API call go into the bus request message.
The ApiClient uses Retrofit to make the async API call, and posts a 'result message' containing the result to the event bus on success, and an 'error message' if there's an error. Each API call has it's own triplet of bus messages - xxxRequest, xxxResponse, xxxError.
So, when an Activity or a Fragment (or other, non-ui class) wants to invoke the api, it registers to the bus for the xxxResponse and xxxError messages, and then posts an xxxRequest message to the bus.
The only potential down-sides are:
The ApiClient is a singleton, and is owned by the Application class, just so that it doesn't get garbage collected.
You wind up with a large number of Message classes - I deal with this by putting them into their own package.
Several classes in Android API require a Context parameter in their constructor, for example ArrayAdapter, SQLiteOpenHelper or Intent. When creating such an object from inside an Activity, what context instance is more appropriate to pass to them: this (the activity instance itself) or the object returned by the activity's getApplicationContext() method and why?
Up to now, I have used both and didn't see any difference in the resulting functionality. Is there any rule of thumb?
From the docs of getApplicationContext() method:
Return the context of the single, global Application object of the
current process. This generally should only be used if you need a
Context whose lifecycle is separate from the current context, that is
tied to the lifetime of the process rather than the current component.
Consider for example how this interacts with {# #registerReceiver(BroadcastReceiver, IntentFilter)}:
If used from an Activity context, the receiver is being registered
within that activity. This means that you are expected to unregister
before the activity is done being destroyed; in fact if you do not do
so, the framework will clean up your leaked registration as it removes
the activity and log an error. Thus, if you use the Activity context
to register a receiver that is static (global to the process, not
associated with an Activity instance) then that registration will be
removed on you at whatever point the activity you used is destroyed.
If used from the Context returned here, the receiver is being
registered with the global state associated with your application.
Thus it will never be unregistered for you. This is necessary if the
receiver is associated with static data, not a particular component.
However using the ApplicationContext elsewhere can easily lead to
serious leaks if you forget to unregister, unbind, etc.
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.