After that I started using non-inner and... now I see A LOT of benefits. The second is, keep a reference of your running AsyncTask in the Application Class - developer.android.com/reference/android/... Everytime you start an AsyncTask, set it on the Application and when it finishes it set it to null. When a fragment/activity starts you can check if any AsyncTask is running (by checking if it's null or not on the Application) and then set the reference inside to whatever you want (activity, fragment etc so you can do callbacks).
This will solve your problem: If you only have 1 AsyncTask running at any determined time you can add a simple reference: AsyncTask asyncTask = null; Else, have in the Aplication a HashMap with references to them. The progress dialog can follow the exact same principle.
I agreed as long as you bind AsyncTask's life cycle to its Parent (by defining AsyncTask as an inner class of Activity/Fragment), it is fairly hard to make your AsyncTask escape from its parent's lifecycle recreation, however, I don't like your solution, it looks just so hacky. – yorkw Dec 16 at 1:27 The question is.. do you have a better solution? – NeTeInStEiN 2 days ago I'm going to have to agree with @yorkw here, this solution aws presented to me a while ago when I was dealing with this issue without using fragments (Activity based app).
This question: stackoverflow. Com/questions/2620917/… has the same answer, and I agree with one of the comments that says "Application instance has its own life cycle - it can be killed by OS too, so this solution may cause a hard-to-reproduce bug" – blindstuff 2 days ago Still I don't see any other way that is less "hacky" as @yorkw said. I'm been using it in several apps, and with some attention to the possible problems it all works great.
– NeTeInStEiN 2 days ago.
Fragments can actually make this a lot easier. Just use the method Fragment. SetRetainInstance(boolean) to have your fragment instance retained across configuration changes.
Note that this is the recommended replacement for Activity. OnRetainnonConfigurationInstance() in the docs. If for some reason you really don't want to use a retained fragment, there are other approaches you can take.
Note that each fragment has a unique identifier returned by Fragment.getId(). You can also find out if a fragment is being torn down for a config change through Fragment.getActivity(). IsChangingConfigurations().
So, at the point where you would decide to stop your AsyncTask (in onStop() or onDestroy() most likely), you could for example check if the configuration is changing and if so stick it in a static SparseArray under the fragment's identifier, and then in your onCreate() or onStart() look to see if you have an AsyncTask in the sparse array available.
My approach is to use delegation design pattern, in general, we can isolate the actual business logic (read data from internet or database or whatsoever) from AsyncTask (the delegator) to BusinessDAO (the delegate), in your AysncTask.doInBackground() method, delegate the actual task to BusinessDAO, then implement a singleton process mechanism in BusinessDAO, so that multiple call to BusinessDAO.doSomething() will just trigger one actual task running each time and waiting for the task result. The idea is retain the delegate (i.e. BusinessDAO) during the configuration change, instead of the delegator (i.e.
AsyncTask). Create/Implement our own Application, the purpose is to create/initialize BusinessDAO here, so that our BusinessDAO's lifecycle is application scoped, not activity scoped, note that you need change AndroidManifest. Xml to use MyApplication: public class MyApplication extends android.app.
Application { private BusinessDAO businessDAO; @Override public void onCreate() { super.onCreate(); businessDAO = new BusinessDAO(); } pubilc BusinessDAO getBusinessDAO() { return businessDAO; } } Our existing Activity/Fragement are mostly unchanged, still implement AsyncTask as an inner class and involve AsyncTask.execute() from Activity/Fragement, the difference now is AsyncTask will delegate the actual task to BusinessDAO, so during the configuration change, a second AsyncTask will be initialized and executed, and call BusinessDAO.doSomething() second time, however, second call to BusinessDAO.doSomething() will not trigger a new running task, instead, waiting for current running task to finish: public class LoginFragment extends Fragment { ... ... public class LoginAsyncTask extends AsyncTask { // get a reference of BusinessDAO from application scope. BusinessDAO businessDAO = ((MyApplication) getApplication()).getBusinessDAO(); @Override protected Boolean doInBackground(String... args) { businessDAO.doSomething(); return true; } protected void onPostExecute(Boolean result) { //Handle task result and update UI stuff. } } ... ... } Inside BusinessDAO, implement singleton process mechanism, for example: public class BusinessDAO { ExecutorCompletionService completionExecutor = new ExecutorCompletionServiceNewFixedThreadPool(1)); Future myFutureTask = null; public void doSomething() { if (myFutureTask == null) { // nothing running at the moment, submit a new callable task to run.
MyTask myTask = new MyTask(); myFutureTask = completionExecutor. Submit(myTask); } // Task already submitted and running, waiting for the running task to finish.MyFutureTask.get(); } // If you've never used this before, Callable is similar with Runnable, with ability to return result and throw exception. Private class MyTask extends Callable { public MyAsyncTask call() { // do your job here.
Return this; } } } I am not 100% sure if this will work, moreover, the sample code snippet should be considered as pseudocode. I am just trying to give you some clue from design level. Any feedback or suggestions are welcome and appreciated.
You could make the AsyncTask a static field. If you need a context, you should ship your application context. This will avoid memory leaks, otherwise you'd keep a reference to your entire activity.
I cant really gove you an answer,but what I can give you is a way to a solution, that is you have to find the anglde that you relate to or peaks your interest. A good paper is one that people get drawn into because it reaches them ln some way.As for me WW11 to me, I think of the holocaust and the effect it had on the survivors, their families and those who stood by and did nothing until it was too late.