Issue
I have created an App which requires to run a operation in background for quite some time suppose 10 - 15 mins.
I am running this operation in An AsyncTask. So during this time the user is minimizing the Screen and using his other apps in his phone as usual.
When this operation is started I am creating a Progress Dialog box and then keep updating it regularly.
But this is the error which I am receiving sometimes very rarely once the operation is over
Fatal Exception: java.lang.IllegalArgumentException
View=DecorView@1234567[ABC:] not attached to window manager PackageName
And this is the detailed stack log
Fatal Exception: java.lang.IllegalArgumentException View=DecorView@1234567[ABC:] not attached to window manager PackageName
at android.view.WindowManagerGlobal.findViewLocked(WindowManagerGlobal.java:508) at android.view.WindowManagerGlobal.removeView(WindowManagerGlobal.java:417) at android.view.WindowManagerImpl.removeViewImmediate(WindowManagerImpl.java:136) at android.app.Dialog.dismissDialog(Dialog.java:446) at android.app.Dialog.dismiss(Dialog.java:429) at android.app.Dialog.cancel(Dialog.java:1353) at PACKAGENAME at android.app.Activity.runOnUiThread(Activity.java:6078) at PACKAGENAME at PACKAGENAME at android.os.AsyncTask.finish(AsyncTask.java:667) at android.os.AsyncTask.-wrap1(AsyncTask.java) at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:684) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:154) at android.app.ActivityThread.main(ActivityThread.java:6823) at java.lang.reflect.Method.invoke(Method.java) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1557) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1445)
To my knowledge this error is because the Android OS wanted to release some memory hence my App was closed since this was not visible to the user. But is there any way to tackle this thing?
Any help would be really appreciated.
EDIT: This is the code which I am using
public class load extends AsyncTask<Void, Void, Void> {
@Override
public Void doInBackground(Void... voids) {
for(int i=0;i<number;i++){
PerformSomeOperation();
UpdateTheProgress();
}
return null;
}
@Override
protected void onPostExecute(Void n) {
runOnUiThread(new Runnable() {
@Override
public void run() {
mProgressDialog.cancel();
CreateAnotherDialog();//This dialog is created to show the user completion of the progress.
}
});
}
Solution
You're having this crash because you're trying to update the UI when it's in the background so your Activity
could be destroyed at that point. By the way, onPostExecute
runs your code on the main thread already but as you're sending a separate message to the main looper you're postponing your logic a bit which can also cause a problem. Moreover, But the main question - why to update the UI if it's not visible to the user anyways?
Also, because you're using the AsyncTask
as an inner class you may leak (though temporarily) your Activity
object as it's referenced implicitly by the task.
From Android Documentation:
AsyncTasks should ideally be used for short operations (a few seconds at the most.) If you need to keep threads running for long periods of time, it is highly recommended you use the various APIs provided by the java.util.concurrent package such as Executor, ThreadPoolExecutor and FutureTask.
So, don't use AsyncTasks for long-running operations. A better approach would be to use:
IntentService
together withBroadcastReceiver
to communicate with yourActivity
/Fragment
(inAPI >= 26
you should useJobIntentService
asIntentService
may misbehave due to new restrictions on background services).RxAndroid
(or justExecutorService
/Thread
) together withArchitecture-Components
(more specifically withLiveData
) - this way a result of your task can be cached or it can survive the config change.
My personal favourite is option 2.
Answered By - Anatolii
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.