I am writing an SDK that allows a user of the SDK to request data and have it returned to them asynchronously.
To access the SDK I decided to use a Singleton pattern. I do this because they may want to use the SDK from several different activities or fragments and I want each component that uses it to have the same instance. So the user will call MyClass.getInstance() which will return an instance of MyClass to them. Then they can call myClass.doAsynchronousOp(), etc...
One issues I am having is that when a user calls a method on the SDK it will do a bunch of work and I don't want to block the caller's thread. So, the solution I came up with was to create an instance of a HandlerThread when the class is first instantiated. Then when the user calls a method on the singleton class that is supposed to be asynchronous I create a Runnable and run it using the HandlerThread. This seems to work pretty well, but I have a few questions:
1) Let's say the user gets an instance of my singleton and calls one of the asynchronous methods. Now the class is holding a running HandlerThread. When the activity is destroyed is it imperative that I call .quit() on my HandlerThread? If so, I pretty much need to make the user call a method like myClass.unregister() in the onDestroy() method of they're activity which is ok, but I'd rather be able to do it automatically for them. Is it bad practice to not call .quit() on my HandlerThread when the application component holding it gets destroyed?
2) Since this is a singleton I'm noticing that even if the Activity that is holding it is destroyed, the instance can remain in memory. So if the Activity is destroyed and then recreated (device rotation) then my constructor of the singleton doesn't get run again. This is problematic because I setup my HandlerThread in the constructor. If I call .quit() on the HandlerThread when the Activity gets destroyed and then the activity gets recreated, the HandlerThread still exists in the singleton object, but now it's in the Terminated state and I can't use it. Is there a good way around this?
Maybe a more general question: How can I provide asynchronous access to my SDK without running into thread lifecycle vs. android component lifecycle issues?
Related
I am learning Android app development from Udacity.com by Google engineers and they said,
"It is not a good idea to use 'AsyncTask' as it is not attached to an activity life cycle. The virtual machine will hold on to the activity object as long as the Asynctask is running, even after Android has called onDestroy( ) method for the activity and expect it to be discarded.
If you rotate your phone, the behavior is to destroy the current activity and instantiate a new one. The naive AsyncTask implementation now has two threads trying to do the same update. So it is not the best pattern for a potentially very long running background operation , such as fetching from web services. If you leave the app, the asyncTask will run as long as as the process is kept alive , but will run at a lower priority, and your process will be the first thing to be killed if the device needs more resources. "
1) If using AsyncTask is disadvantageous why was it created? What would have been the design philosophy or the cause to create it in spite of having services(or something similar to achieve same kind of functionality)?
2) What are the situations where Asynctask should be used for betterment compared to Services/similar options available in Android?
3) What are the situations/places Asynctask should never be used?
Please do not downvote this question. I searched Stackoverflow and I couldn't find a similar question.
Advantages of AsyncTask
Provides generic solution for all network calls
Publish progress to UI while executing.
Run Asynchronously
Easy to maintain and read.
Problems in AysncTask
When you rotate your screen, Activity gets destroyed, so AsyncTask will not have a valid reference to publish data from onPostExecute(). In order to retain it, you need to usesetRetainState(true) if calling from fragment or onConfigChanges() if calling from activity method of an activity.
If activity gets finished, AsyncTask execution will not cancelled automatically, you need to cancel them else they will keep on running in the background.
If any exception occurs while performing network task, you need to handle them manually.
Whereas AsycTask, Services, IntentService, Threads all run on different threads and all serve different purpose.
please read more detail here.
So you need to decide when to use which component while performing non UI operations.
I started Android a week ago and I have a design question.
I have two activities A and B. I'm currently on activity A. In activity A I start a thread that listens to network messages. On receiving start in the background thread over the network, I need to go into activity B.
Question: Can I simply call startActivity(B.class) from the background thread?
If not, I suppose I use a Handler to call startActivity(B.class) from activity A thread.
Question: Will my background thread still continue to execute once activity A, the one that created it is destroyed, provided I take care that there are no dead references?
Eventually I receive a stop message in the background thread, again, over the network. Now I need to go back to activity A (or some other activity).
Question: Should I replace the handler instance in the background thread class with a new handler instance created in Activity B? I reckon I'll have to pass the thread object to activity B when I start it. I'll presumably have to take care of the race condition when switching out the handler instances.
All of this seems... complicated. Is there a more elegant way to achieve this? Services? Loopers? All of this is new and the tools/design choices are a bit confusing.
If you are having multiple Activities then this isn't the ideal way of doing it.
Once Activity destroys your thread will have no more reference though it is running in the background. Use a singleton class to create the thread and register your respective handlers to that class, you will be able to communicate to the activities easily through these handlers.
At runtime, I am using a callback pattern to have generic code run and use the callback when finished to execute code on the GUI. So in my handler I use the runOnUiThread function against the callback.
These are all async http calls. At runtime if I interrupt and use the back button and go to another fragment for example, the system will swap out the fragments and run both callbacks (the new fragment one on the correct callback, and the old callback that should have ran on the old fragment on the new current fragment). This is wrong, the new fragment gets both callbacks but when it was initialized it was assigned to the other fragment...
This makes no sense and you can only observe the behavior by switching fragments at runtime before an async call finishes. I don't see how it's possible, in the code I check if callback is null so it should have been garbage collected and how it runs on the new callback I don't know how it's possible....there's no additional assignment happening to change this. It's almost like it's just looking in memory for the function signature and running it even though when it does it's on the wrong object.
Does anyone have any clue what's going on? I've surpressed it with an ugly piece code, I just don't know how this is possible?
I understand the obvious candidates are if I assigned it again somewhere, but the answer is no. When the fragment is created it creates an object, assigns itself as the callback, and processing begins so when the fragment is destroyed it should be too. But the async task is still executing which is fine, why it does a callback on the new thread on the main gui I guess is because of runOnUiThread, so that function is somehow changing what the callback object points to in memory?
Its your code :-)
There is no magic happening 'behind the scenes' in Android and no references are changed.
Many have problems like yours, and its always because they assume that the Android system is somehow cleaning up when a fragment or activity instance is replaced or removed. It isn't, and therefore the callbacks are still executed, on a obsolete fragment or activity.
runOnUiThread takes a Runnable and runs it when the UI thread have spare time (after invoking lifecycle methods and finished rendering). Its not magic either :-)
I'm developing an android application, and would like to know the difference between a service started with startService() and a singleton class performing the same code I put in startService().
So, for example if I have a VideoRecordingService service set to record a video from the camera on it's start, and a CameraRecorderClass singleton class which have a StartRecording() method that also records a video from the camera, how do they differ?
They both non-related to any activity lifecycle, and they both use the main thread to do it's work.
Thanks
Service is mainly used when you want to do some background operation. For eg:- Playing music in your application. So, if you don't have any Activity running you can play music using Service.
While your Singleton instance would not be working if you close your application/activity if unless you are performing it in some background task. Also, Service will restart automatically if you return START_STICKY from onStartCommand when your Service is killed due to some reason.
So, in your case if you really want to do some long background running operation then its better to use Service instead of your Singleton instance.
When using startService it creates a new instance of that class, it can have a context and do a wide range of things that the Service class inherits. You can create this anywhere in your application where you have a context, and you can start and stop it multiple times (using startService and stopSelf)
With a singleton class, well, its a static object that you can only have once instance of (unless you want to create more I guess?). The static object can isn't much different, however it doesn't have a context and all that nice android stuff that comes with a class (unless you pass it a context or what ever you may need).
A service can also be run without needing to invoke it by using a activity, or showing a UI, it can run in the background with no UI, and can be started using a broadcast listener without interrupting the user, as long as the service is running then the service shouldn't be automatically closed by the system, rather then if you started an async task in the singleton and then closed the activity and the activity was destroyed.
There may be more to it. But you would have to look into dalvik..
I've searched everywhere a manner to have the equivalent of a main() function (yes function not method) inside a Android application but failed...
Typically what I would want to do is:
void main()
{
// do some really nice initialisations stuff here
// ... let the app does his life, I really don't care
// do some final stuff here before leaving
}
The nearest approach I've seen so far is to use a SplashScreen and override the OnCreate() method. The problem is that is not acceptable from my point of view.
Why? Because a SplashScreen is nothing than an Activity tagged as a LAUNCHER.
That makes it to appear in the apps list, thing I don't want when I develop an app widget.
Furthermore, where to place my code just before the app destroy? In the onDestroy() method?
No, once again, this is not reliable. Android can decide to delete my instance whereas the application is still running.
Well, in fact, I take for principle that every components of my app are running in the same process since I don't mention explicitely in the Manifest that I wan't a component to run in its own process.
In the case of an app widget, I've placed my init code on the first call of onUpdate() method. I think it's a good bet. Then this app widget (AppWidgetProvider more precisely) is in charge to launch any activity as its will.
The "DataBase" for all the app is defined in a separate Singleton like this:
public class MyDataBase {
public static MyDataBase getInstance() {
if (instance_ == null)
instance_ = new DataBase();
return instance_;
}
public void load();
public void save();
static MyDataBase instance_ = null;
public int myInt;
public String myString;
public Object myObject;
etc..
}
With this Singleton I'm sure at least, its lifecycle is the same as the entire app itself.
To back with that AppWidgetProvider, I have to trick a little. Indeed, Android can decide to delete its instance whereas some other activities are still on place and the process is still running. So for example, systematically loading my DataBase in the first call of the OnUpdate() is unnecessary and overkill. What I do is having a static boolean value that indicates if the DataBase have been loaded for the lifecycle of this process or not.
Thus, the AppWidgetProvider can be instanciated tons of time, as long as the Singleton DataBase persists (so the process), it will not reload the DataBase each time, got it?
(yes difficult to be clear...)
About the cleanup code of the app, I thought to override the finalize() method of my DataBase Singleton, but well, I'm really not sure it's a good idea since the moment of the call of this method is totally unpredictable. I suppose it would be called if you suddently power off your Android, but well I'm not sure of anything here, thus so far, I didn't found a solution for that part.
Any comment or something less tricky that what I currently do is welcome.
Thanks.
onResume() is the function that will be invariably reached before starting you app, so you could either put the 'main' code in the onCreate() method or the onResume().
onPause() is ALWAYS called before destroying the app, either by the user or the OS.
There is great explanation regarding the lifecycle in the Android documentation:
http://developer.android.com/training/basics/activity-lifecycle/starting.html
For the initialisation you can over-ride the onCreate method of the Application class:
Called when the application is starting, before any activity, service, or receiver objects (excluding content providers) have been created. Implementations should be as quick as possible (for example using lazy initialization of state) since the time spent in this function directly impacts the performance of starting the first activity, service, or receiver in a process. If you override this method, be sure to call super.onCreate()
Termination is harder to deal with. You'll probably have to monitor each component of your application separately. If you are targeting API level 14 or later you can use Application.registerActivityLifecycleCallbacks to help with this.
The nearest approach I've seen so far is to use a SplashScreen and
override the OnCreate() method. The problem is that is not acceptable
from my point of view. Why? Because a SplashScreen is nothing than an
Activity tagged as a LAUNCHER.
It's because Android is formed with several activities and those activities have life cycles. So every activities start from onCreate() then finishes at onDestroy().
http://developer.android.com/training/basics/activity-lifecycle/starting.html
That makes it to appear in the apps list, thing I don't want when I
develop an app widget. Furthermore, where to place my code just before
the app destroy? In the onDestroy() method? No, once again, this is
not reliable. Android can decide to delete my instance whereas the
application is still running.
In a scenario that user presses home button to exit from your app, your current activity is more likely to invoke onPause() method (only when the activity has no other processes to finish). However, when user force closes (terminates) your whole application by ending process. Then you don't have to worry about invoking any methods or what so ever because Android itself will close anything related to your application automatically.
To back with that AppWidgetProvider, I have to trick a little. Indeed,
Android can decide to delete its instance whereas some other
activities are still on place and the process is still running. So for
example, systematically loading my DataBase in the first call of the
OnUpdate() is unnecessary and overkill. What I do is having a static
boolean value that indicates if the DataBase have been loaded for the
lifecycle of this process or not. Thus, the AppWidgetProvider can be
instanciated tons of time, as long as the Singleton DataBase persists
(so the process), it will not reload the DataBase each time, got it?
(yes difficult to be clear...)
The example you have posted for singleton database connection is not bad I think, but there are better ways to get the job done cleanly and more effectively. For example hibernate framework connection pooling