How to handle screen orientation change when progress dialog and background thread active?












500















My program does some network activity in a background thread. Before starting, it pops up a progress dialog. The dialog is dismissed on the handler. This all works fine, except when screen orientation changes while the dialog is up (and the background thread is going). At this point the app either crashes, or deadlocks, or gets into a weird stage where the app does not work at all until all the threads have been killed.



How can I handle the screen orientation change gracefully?



The sample code below matches roughly what my real program does:



public class MyAct extends Activity implements Runnable {
public ProgressDialog mProgress;

// UI has a button that when pressed calls send

public void send() {
mProgress = ProgressDialog.show(this, "Please wait",
"Please wait",
true, true);
Thread thread = new Thread(this);
thread.start();
}

public void run() {
Thread.sleep(10000);
Message msg = new Message();
mHandler.sendMessage(msg);
}

private final Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
mProgress.dismiss();
}
};
}


Stack:



E/WindowManager(  244): Activity MyAct has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView@433b7150 that was originally added here
E/WindowManager( 244): android.view.WindowLeaked: Activity MyAct has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView@433b7150 that was originally added here
E/WindowManager( 244): at android.view.ViewRoot.<init>(ViewRoot.java:178)
E/WindowManager( 244): at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:147)
E/WindowManager( 244): at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:90)
E/WindowManager( 244): at android.view.Window$LocalWindowManager.addView(Window.java:393)
E/WindowManager( 244): at android.app.Dialog.show(Dialog.java:212)
E/WindowManager( 244): at android.app.ProgressDialog.show(ProgressDialog.java:103)
E/WindowManager( 244): at android.app.ProgressDialog.show(ProgressDialog.java:91)
E/WindowManager( 244): at MyAct.send(MyAct.java:294)
E/WindowManager( 244): at MyAct$4.onClick(MyAct.java:174)
E/WindowManager( 244): at android.view.View.performClick(View.java:2129)
E/WindowManager( 244): at android.view.View.onTouchEvent(View.java:3543)
E/WindowManager( 244): at android.widget.TextView.onTouchEvent(TextView.java:4664)
E/WindowManager( 244): at android.view.View.dispatchTouchEvent(View.java:3198)


I have tried to dismiss the progress dialog in onSaveInstanceState, but that just prevents an immediate crash. The background thread is still going, and the UI is in partially drawn state. Need to kill the whole app before it starts working again.










share|improve this question




















  • 1





    Considering the answers you have received, you should change the accepted answer in favor of the best, shouln't you?

    – rds
    Mar 10 '11 at 16:32











  • See also a former question stackoverflow.com/questions/456211/…

    – rds
    Mar 21 '11 at 13:57








  • 3





    All, Got a really great explanation and possible solutions to this problem. Go through http://blog.doityourselfandroid.com/2010/11/14/handling-progress-dialogs-and-screen-orientation-changes/ Lemme know if this helped.

    – arcamax
    May 30 '11 at 19:46






  • 2





    There is a rather complete explanation on how to retain asynchronous background tasks across screen orientations in this blog post. Check it out!

    – Adrian Monk
    Jan 15 '14 at 20:15













  • Simply set android:configChanges="orientation|screenSize" to Activity in manifest.It will stop android to recreate its activity

    – Xar E Ahmer
    Apr 28 '15 at 11:07


















500















My program does some network activity in a background thread. Before starting, it pops up a progress dialog. The dialog is dismissed on the handler. This all works fine, except when screen orientation changes while the dialog is up (and the background thread is going). At this point the app either crashes, or deadlocks, or gets into a weird stage where the app does not work at all until all the threads have been killed.



How can I handle the screen orientation change gracefully?



The sample code below matches roughly what my real program does:



public class MyAct extends Activity implements Runnable {
public ProgressDialog mProgress;

// UI has a button that when pressed calls send

public void send() {
mProgress = ProgressDialog.show(this, "Please wait",
"Please wait",
true, true);
Thread thread = new Thread(this);
thread.start();
}

public void run() {
Thread.sleep(10000);
Message msg = new Message();
mHandler.sendMessage(msg);
}

private final Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
mProgress.dismiss();
}
};
}


Stack:



E/WindowManager(  244): Activity MyAct has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView@433b7150 that was originally added here
E/WindowManager( 244): android.view.WindowLeaked: Activity MyAct has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView@433b7150 that was originally added here
E/WindowManager( 244): at android.view.ViewRoot.<init>(ViewRoot.java:178)
E/WindowManager( 244): at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:147)
E/WindowManager( 244): at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:90)
E/WindowManager( 244): at android.view.Window$LocalWindowManager.addView(Window.java:393)
E/WindowManager( 244): at android.app.Dialog.show(Dialog.java:212)
E/WindowManager( 244): at android.app.ProgressDialog.show(ProgressDialog.java:103)
E/WindowManager( 244): at android.app.ProgressDialog.show(ProgressDialog.java:91)
E/WindowManager( 244): at MyAct.send(MyAct.java:294)
E/WindowManager( 244): at MyAct$4.onClick(MyAct.java:174)
E/WindowManager( 244): at android.view.View.performClick(View.java:2129)
E/WindowManager( 244): at android.view.View.onTouchEvent(View.java:3543)
E/WindowManager( 244): at android.widget.TextView.onTouchEvent(TextView.java:4664)
E/WindowManager( 244): at android.view.View.dispatchTouchEvent(View.java:3198)


I have tried to dismiss the progress dialog in onSaveInstanceState, but that just prevents an immediate crash. The background thread is still going, and the UI is in partially drawn state. Need to kill the whole app before it starts working again.










share|improve this question




















  • 1





    Considering the answers you have received, you should change the accepted answer in favor of the best, shouln't you?

    – rds
    Mar 10 '11 at 16:32











  • See also a former question stackoverflow.com/questions/456211/…

    – rds
    Mar 21 '11 at 13:57








  • 3





    All, Got a really great explanation and possible solutions to this problem. Go through http://blog.doityourselfandroid.com/2010/11/14/handling-progress-dialogs-and-screen-orientation-changes/ Lemme know if this helped.

    – arcamax
    May 30 '11 at 19:46






  • 2





    There is a rather complete explanation on how to retain asynchronous background tasks across screen orientations in this blog post. Check it out!

    – Adrian Monk
    Jan 15 '14 at 20:15













  • Simply set android:configChanges="orientation|screenSize" to Activity in manifest.It will stop android to recreate its activity

    – Xar E Ahmer
    Apr 28 '15 at 11:07
















500












500








500


244






My program does some network activity in a background thread. Before starting, it pops up a progress dialog. The dialog is dismissed on the handler. This all works fine, except when screen orientation changes while the dialog is up (and the background thread is going). At this point the app either crashes, or deadlocks, or gets into a weird stage where the app does not work at all until all the threads have been killed.



How can I handle the screen orientation change gracefully?



The sample code below matches roughly what my real program does:



public class MyAct extends Activity implements Runnable {
public ProgressDialog mProgress;

// UI has a button that when pressed calls send

public void send() {
mProgress = ProgressDialog.show(this, "Please wait",
"Please wait",
true, true);
Thread thread = new Thread(this);
thread.start();
}

public void run() {
Thread.sleep(10000);
Message msg = new Message();
mHandler.sendMessage(msg);
}

private final Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
mProgress.dismiss();
}
};
}


Stack:



E/WindowManager(  244): Activity MyAct has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView@433b7150 that was originally added here
E/WindowManager( 244): android.view.WindowLeaked: Activity MyAct has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView@433b7150 that was originally added here
E/WindowManager( 244): at android.view.ViewRoot.<init>(ViewRoot.java:178)
E/WindowManager( 244): at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:147)
E/WindowManager( 244): at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:90)
E/WindowManager( 244): at android.view.Window$LocalWindowManager.addView(Window.java:393)
E/WindowManager( 244): at android.app.Dialog.show(Dialog.java:212)
E/WindowManager( 244): at android.app.ProgressDialog.show(ProgressDialog.java:103)
E/WindowManager( 244): at android.app.ProgressDialog.show(ProgressDialog.java:91)
E/WindowManager( 244): at MyAct.send(MyAct.java:294)
E/WindowManager( 244): at MyAct$4.onClick(MyAct.java:174)
E/WindowManager( 244): at android.view.View.performClick(View.java:2129)
E/WindowManager( 244): at android.view.View.onTouchEvent(View.java:3543)
E/WindowManager( 244): at android.widget.TextView.onTouchEvent(TextView.java:4664)
E/WindowManager( 244): at android.view.View.dispatchTouchEvent(View.java:3198)


I have tried to dismiss the progress dialog in onSaveInstanceState, but that just prevents an immediate crash. The background thread is still going, and the UI is in partially drawn state. Need to kill the whole app before it starts working again.










share|improve this question
















My program does some network activity in a background thread. Before starting, it pops up a progress dialog. The dialog is dismissed on the handler. This all works fine, except when screen orientation changes while the dialog is up (and the background thread is going). At this point the app either crashes, or deadlocks, or gets into a weird stage where the app does not work at all until all the threads have been killed.



How can I handle the screen orientation change gracefully?



The sample code below matches roughly what my real program does:



public class MyAct extends Activity implements Runnable {
public ProgressDialog mProgress;

// UI has a button that when pressed calls send

public void send() {
mProgress = ProgressDialog.show(this, "Please wait",
"Please wait",
true, true);
Thread thread = new Thread(this);
thread.start();
}

public void run() {
Thread.sleep(10000);
Message msg = new Message();
mHandler.sendMessage(msg);
}

private final Handler mHandler = new Handler() {
@Override
public void handleMessage(Message msg) {
mProgress.dismiss();
}
};
}


Stack:



E/WindowManager(  244): Activity MyAct has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView@433b7150 that was originally added here
E/WindowManager( 244): android.view.WindowLeaked: Activity MyAct has leaked window com.android.internal.policy.impl.PhoneWindow$DecorView@433b7150 that was originally added here
E/WindowManager( 244): at android.view.ViewRoot.<init>(ViewRoot.java:178)
E/WindowManager( 244): at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:147)
E/WindowManager( 244): at android.view.WindowManagerImpl.addView(WindowManagerImpl.java:90)
E/WindowManager( 244): at android.view.Window$LocalWindowManager.addView(Window.java:393)
E/WindowManager( 244): at android.app.Dialog.show(Dialog.java:212)
E/WindowManager( 244): at android.app.ProgressDialog.show(ProgressDialog.java:103)
E/WindowManager( 244): at android.app.ProgressDialog.show(ProgressDialog.java:91)
E/WindowManager( 244): at MyAct.send(MyAct.java:294)
E/WindowManager( 244): at MyAct$4.onClick(MyAct.java:174)
E/WindowManager( 244): at android.view.View.performClick(View.java:2129)
E/WindowManager( 244): at android.view.View.onTouchEvent(View.java:3543)
E/WindowManager( 244): at android.widget.TextView.onTouchEvent(TextView.java:4664)
E/WindowManager( 244): at android.view.View.dispatchTouchEvent(View.java:3198)


I have tried to dismiss the progress dialog in onSaveInstanceState, but that just prevents an immediate crash. The background thread is still going, and the UI is in partially drawn state. Need to kill the whole app before it starts working again.







android android-activity android-dialog






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Jan 15 '14 at 20:16









Alex Lockwood

74.5k33183232




74.5k33183232










asked Jul 10 '09 at 21:05









Heikki ToivonenHeikki Toivonen

20.8k103542




20.8k103542








  • 1





    Considering the answers you have received, you should change the accepted answer in favor of the best, shouln't you?

    – rds
    Mar 10 '11 at 16:32











  • See also a former question stackoverflow.com/questions/456211/…

    – rds
    Mar 21 '11 at 13:57








  • 3





    All, Got a really great explanation and possible solutions to this problem. Go through http://blog.doityourselfandroid.com/2010/11/14/handling-progress-dialogs-and-screen-orientation-changes/ Lemme know if this helped.

    – arcamax
    May 30 '11 at 19:46






  • 2





    There is a rather complete explanation on how to retain asynchronous background tasks across screen orientations in this blog post. Check it out!

    – Adrian Monk
    Jan 15 '14 at 20:15













  • Simply set android:configChanges="orientation|screenSize" to Activity in manifest.It will stop android to recreate its activity

    – Xar E Ahmer
    Apr 28 '15 at 11:07
















  • 1





    Considering the answers you have received, you should change the accepted answer in favor of the best, shouln't you?

    – rds
    Mar 10 '11 at 16:32











  • See also a former question stackoverflow.com/questions/456211/…

    – rds
    Mar 21 '11 at 13:57








  • 3





    All, Got a really great explanation and possible solutions to this problem. Go through http://blog.doityourselfandroid.com/2010/11/14/handling-progress-dialogs-and-screen-orientation-changes/ Lemme know if this helped.

    – arcamax
    May 30 '11 at 19:46






  • 2





    There is a rather complete explanation on how to retain asynchronous background tasks across screen orientations in this blog post. Check it out!

    – Adrian Monk
    Jan 15 '14 at 20:15













  • Simply set android:configChanges="orientation|screenSize" to Activity in manifest.It will stop android to recreate its activity

    – Xar E Ahmer
    Apr 28 '15 at 11:07










1




1





Considering the answers you have received, you should change the accepted answer in favor of the best, shouln't you?

– rds
Mar 10 '11 at 16:32





Considering the answers you have received, you should change the accepted answer in favor of the best, shouln't you?

– rds
Mar 10 '11 at 16:32













See also a former question stackoverflow.com/questions/456211/…

– rds
Mar 21 '11 at 13:57







See also a former question stackoverflow.com/questions/456211/…

– rds
Mar 21 '11 at 13:57






3




3





All, Got a really great explanation and possible solutions to this problem. Go through http://blog.doityourselfandroid.com/2010/11/14/handling-progress-dialogs-and-screen-orientation-changes/ Lemme know if this helped.

– arcamax
May 30 '11 at 19:46





All, Got a really great explanation and possible solutions to this problem. Go through http://blog.doityourselfandroid.com/2010/11/14/handling-progress-dialogs-and-screen-orientation-changes/ Lemme know if this helped.

– arcamax
May 30 '11 at 19:46




2




2





There is a rather complete explanation on how to retain asynchronous background tasks across screen orientations in this blog post. Check it out!

– Adrian Monk
Jan 15 '14 at 20:15







There is a rather complete explanation on how to retain asynchronous background tasks across screen orientations in this blog post. Check it out!

– Adrian Monk
Jan 15 '14 at 20:15















Simply set android:configChanges="orientation|screenSize" to Activity in manifest.It will stop android to recreate its activity

– Xar E Ahmer
Apr 28 '15 at 11:07







Simply set android:configChanges="orientation|screenSize" to Activity in manifest.It will stop android to recreate its activity

– Xar E Ahmer
Apr 28 '15 at 11:07














26 Answers
26






active

oldest

votes


















146














When you switch orientations, Android will create a new View. You're probably getting crashes because your background thread is trying to change the state on the old one. (It may also be having trouble because your background thread isn't on the UI thread)



I'd suggest making that mHandler volatile and updating it when the orientation changes.






share|improve this answer



















  • 13





    You might have pinpointed the reason for the crash. I got rid of the crash, but I still haven't figured out how to restore the UI to the state it was in before the orientation change in a reliable way. But your answer moved me forward, so awarding it as answer.

    – Heikki Toivonen
    Jul 13 '09 at 4:35






  • 4





    You should get an onStart in your activity when the orientation changes. Essentially, you have to reconfigure the view using the old data. So I'd suggest requesting numerical status udpates from the progress bar and rebuilding a new view when you get that new 'onStart' I can't remember offhand if you get a new activity as well but some hunting through the documentation should help.

    – haseman
    Jul 13 '09 at 18:31






  • 6





    Having played with it recently, I can pass on that you do get a new activity when your app changes orientation. (You also get a new view) If you try to update the old view you'll get an exception because the old view has an invalid application context (your old activity) You can kinda get around this by passing in myActivity.getApplicationContext() instead of a pointer to the activity itself.

    – haseman
    Jul 30 '09 at 21:35






  • 1





    Can someone explain the usage/benefit of volatile in this context

    – Xar E Ahmer
    Apr 28 '15 at 10:50






  • 2





    @Nepster Yeah I was wondering about that, too. It would be great if someone explained about the volatile.

    – RestInPeace
    May 2 '15 at 5:27



















257














Edit: Google engineers do not recommend this approach, as described by Dianne Hackborn (a.k.a. hackbod) in this StackOverflow post. Check out this blog post for more information.





You have to add this to the activity declaration in the manifest:



android:configChanges="orientation|screenSize"


so it looks like



<activity android:label="@string/app_name" 
android:configChanges="orientation|screenSize|keyboardHidden"
android:name=".your.package">


The matter is that the system destroys the activity when a change in the configuration occurs. See ConfigurationChanges.



So putting that in the configuration file avoids the system to destroy your activity. Instead it invokes the onConfigurationChanged(Configuration) method.






share|improve this answer





















  • 21





    This is definitely the best solution; as it simply rotates the layout (the behavior you expect in first place). Just be sure to put android:configChanges="orientation|keyboardHidden" (because of phones that have landscape keyboard)

    – kape123
    Oct 13 '10 at 20:41






  • 24





    This seems to be the behaviour I expect. However, the documentation indicates that the activity is destroyed "because any application resource, including layout files, can change based on any configuration value. Thus the only safe way to handle a configuration change is to re-retrieve all resources". And besides orientation, there are many more reasons for the configuration to change: keyboardHidden (I have edited the wiki answer already), uiMode (For example, going in or out of car mode ; night mode changing), etc. I now wonder wether this is actually a good answer.

    – rds
    Mar 10 '11 at 16:49








  • 113





    This is not an acceptable solution. It just masks the true issue.

    – rf43
    Oct 13 '11 at 0:55






  • 18





    Works, but not recommended by Google.

    – Ed Burnette
    Nov 9 '11 at 21:55






  • 21





    Please do not follow this approach here. DDosAttack is completely right. Imagine you are creating a progress dialog for a download or something else that takes a long time. As a user you won't stay on that activity and stare at it. You would switch to the home screen or to another app like a game or a phone call might come in or something else resource hungry that will eventually destroy your activity. And what then? You are facing the same old issue which is NOT solved with that neat little trick. The activity will be recreated all over again when the user comes back.

    – tiguchi
    Oct 1 '12 at 15:22



















66














I came up with a rock-solid solution for these issues that conforms with the 'Android Way' of things. I have all my long-running operations using the IntentService pattern.



That is, my activities broadcast intents, the IntentService does the work, saves the data in the DB and then broadcasts sticky intents. The sticky part is important, such that even if the Activity was paused during during the time after the user initiated the work and misses the real time broadcast from the IntentService we can still respond and pick up the data from the calling Activity. ProgressDialogs can work with this pattern quite nicely with onSaveInstanceState().



Basically, you need to save a flag that you have a progress dialog running in the saved instance bundle. Do not save the progress dialog object because this will leak the entire Activity. To have a persistent handle to the progress dialog, I store it as a weak reference in the application object. On orientation change or anything else that causes the Activity to pause (phone call, user hits home etc.) and then resume, I dismiss the old dialog and recreate a new dialog in the newly created Activity.



For indefinite progress dialogs this is easy. For progress bar style, you have to put the last known progress in the bundle and whatever information you're using locally in the activity to keep track of the progress. On restoring the progress, you'll use this information to re-spawn the progress bar in the same state as before and then update based on the current state of things.



So to summarize, putting long-running tasks into an IntentService coupled with judicious use of onSaveInstanceState() allows you to efficiently keep track of dialogs and restore then across the Activity life-cycle events. Relevant bits of Activity code are below. You'll also need logic in your BroadcastReceiver to handle Sticky intents appropriately, but that is beyond the scope of this.



public void doSignIn(View view) {
waiting=true;
AppClass app=(AppClass) getApplication();
String logingon=getString(R.string.signon);
app.Dialog=new WeakReference<ProgressDialog>(ProgressDialog.show(AddAccount.this, "", logingon, true));
...
}

@Override
protected void onSaveInstanceState(Bundle saveState) {
super.onSaveInstanceState(saveState);
saveState.putBoolean("waiting",waiting);
}

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if(savedInstanceState!=null) {
restoreProgress(savedInstanceState);
}
...
}

private void restoreProgress(Bundle savedInstanceState) {
waiting=savedInstanceState.getBoolean("waiting");
if (waiting) {
AppClass app=(AppClass) getApplication();
ProgressDialog refresher=(ProgressDialog) app.Dialog.get();
refresher.dismiss();
String logingon=getString(R.string.signon);
app.Dialog=new WeakReference<ProgressDialog>(ProgressDialog.show(AddAccount.this, "", logingon, true));
}
}





share|improve this answer


























  • seems a nice solution

    – Derekyy
    Oct 14 '15 at 9:02











  • "I have all my long-running operations using the IntentService pattern." This is not a perfect solution because it is like to shoot out of cannon into sparrows and a lot boilerplate code, for more you can watch youtube.com/watch?v=NJsq0TU0qeg

    – user3871754
    Jun 17 '16 at 11:04





















26














I met the same problem. My activity needs to parse some data from a URL and it's slow. So I create a thread to do so, then show a progress dialog. I let the thread post a message back to UI thread via Handler when it's finished. In Handler.handleMessage, I get the data object (ready now) from thread and populate it to UI. So it's very similar to your example.



After a lot of trial and error it looks like I found a solution. At least now I can rotate screen at any moment, before or after the thread is done. In all tests, the dialog is properly closed and all behaviors are as expected.



What I did is shown below. The goal is to fill my data model (mDataObject) and then populate it to UI. Should allow screen rotation at any moment without surprise.



class MyActivity {

private MyDataObject mDataObject = null;
private static MyThread mParserThread = null; // static, or make it singleton

OnCreate() {
...
Object retained = this.getLastNonConfigurationInstance();
if(retained != null) {
// data is already completely obtained before config change
// by my previous self.
// no need to create thread or show dialog at all
mDataObject = (MyDataObject) retained;
populateUI();
} else if(mParserThread != null && mParserThread.isAlive()){
// note: mParserThread is a static member or singleton object.
// config changed during parsing in previous instance. swap handler
// then wait for it to finish.
mParserThread.setHandler(new MyHandler());
} else {
// no data and no thread. likely initial run
// create thread, show dialog
mParserThread = new MyThread(..., new MyHandler());
mParserThread.start();
showDialog(DIALOG_PROGRESS);
}
}

// http://android-developers.blogspot.com/2009/02/faster-screen-orientation-change.html
public Object onRetainNonConfigurationInstance() {
// my future self can get this without re-downloading
// if it's already ready.
return mDataObject;
}

// use Activity.showDialog instead of ProgressDialog.show
// so the dialog can be automatically managed across config change
@Override
protected Dialog onCreateDialog(int id) {
// show progress dialog here
}

// inner class of MyActivity
private class MyHandler extends Handler {
public void handleMessage(msg) {
mDataObject = mParserThread.getDataObject();
populateUI();
dismissDialog(DIALOG_PROGRESS);
}
}
}

class MyThread extends Thread {
Handler mHandler;
MyDataObject mDataObject;

// constructor with handler param
public MyHandler(..., Handler h) {
...
mHandler = h;
}

public void setHandler(Handler h) { mHandler = h; } // for handler swapping after config change
public MyDataObject getDataObject() { return mDataObject; } // return data object (completed) to caller

public void run() {
mDataObject = new MyDataObject();
// do the lengthy task to fill mDataObject with data
lengthyTask(mDataObject);
// done. notify activity
mHandler.sendEmptyMessage(0); // tell activity: i'm ready. come pick up the data.
}
}


That's what works for me. I don't know if this is the "correct" method as designed by Android -- they claim this "destroy/recreate activity during screen rotation" actually makes things easier, so I guess it shouldn't be too tricky.



Let me know if you see a problem in my code. As said above I don't really know if there is any side effect.






share|improve this answer





















  • 1





    Thanks a lot! The hint to onRetainNonConfigurationInstance() and getLastNonConfigurationInstance() helped me to solve my problem. Thumbs up!

    – sven
    Oct 28 '10 at 13:42



















14














The original perceived problem was that the code would not survive a screen orientation change. Apparently this was "solved" by having the program handle the screen orientation change itself, instead of letting the UI framework do it (via calling onDestroy)).



I would submit that if the underlying problem is that the program will not survive onDestroy(), then the accepted solution is just a workaround that leaves the program with serious other problems and vulnerabilities. Remember that the Android framework specifically states that your activity is at risk for being destroyed almost at any time due to circumstances outside your control. Therefore, your activity must be able to survive onDestroy() and subsequent onCreate() for any reason, not just a screen orientation change.



If you are going to accept handling screen orientation changes yourself to solve the OP's problem, you need to verify that other causes of onDestroy() do not result in the same error. Are you able to do this? If not, I would question whether the "accepted" answer is really a very good one.






share|improve this answer































    14














    My solution was to extend the ProgressDialog class to get my own MyProgressDialog.

    I redefined show() and dismiss() methods to lock the orientation before showing the Dialog and unlock it back when Dialog is dismissed. So when the Dialog is shown and the orientation of the device changes, the orientation of the screen remains until dismiss() is called, then screen-orientation changes according to sensor-values/device-orientation.



    Here is my code:



    public class MyProgressDialog extends ProgressDialog {
    private Context mContext;

    public MyProgressDialog(Context context) {
    super(context);
    mContext = context;
    }

    public MyProgressDialog(Context context, int theme) {
    super(context, theme);
    mContext = context;
    }

    public void show() {
    if (mContext.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT)
    ((Activity) mContext).setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
    else
    ((Activity) mContext).setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
    super.show();
    }

    public void dismiss() {
    super.dismiss();
    ((Activity) mContext).setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);
    }

    }





    share|improve this answer

































      8














      I faced this same problem, and I came up with a solution that didn't invole using the ProgressDialog and I get faster results.



      What I did was create a layout that has a ProgressBar in it.



      <?xml version="1.0" encoding="utf-8"?>
      <RelativeLayout
      xmlns:android="http://schemas.android.com/apk/res/android"
      android:layout_width="fill_parent"
      android:layout_height="fill_parent">
      <ProgressBar
      android:id="@+id/progressImage"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_centerInParent="true"
      />
      </RelativeLayout>


      Then in the onCreate method do the following



      public void onCreate(Bundle icicle) {
      super.onCreate(icicle);
      setContentView(R.layout.progress);
      }


      Then do the long task in a thread, and when that's finished have a Runnable set the content view to the real layout you want to use for this activity.



      For example:



      mHandler.post(new Runnable(){

      public void run() {
      setContentView(R.layout.my_layout);
      }
      });


      This is what I did, and I've found that it runs faster than showing the ProgressDialog and it's less intrusive and has a better look in my opinion.



      However, if you're wanting to use the ProgressDialog, then this answer isn't for you.






      share|improve this answer
























      • This solution is elegant in a simple use case, but has drawbacks. You need to rebuild the full content view. setContentView(R.layout.my_layout); is not sufficient; you need to set all listeners, reset data, etc.

        – rds
        Mar 10 '11 at 23:40













      • @rds you are right. This is really only a solution to a simple case, or if you need to do some heavy lifting in your onCreate method before displaying your view.

        – Pzanno
        Mar 11 '11 at 19:12











      • I don't quite get it. Instead of settings listeners in the onCreate(), as we would typically do, we could set them up in the run(). Am I missing something here?

        – Code Poet
        Dec 11 '11 at 19:03



















      7














      I discovered a solution to this that I haven't yet seen elsewhere. You can use a custom application object that knows if you have background tasks going, instead of trying to do this in the activity that gets destroyed and recreated on orientation change. I blogged about this in here.






      share|improve this answer



















      • 1





        Creating a custom Application is normally used to maintain a global application state. I don't say it doesn't work it, but it seems over-complicated. From the doc "There is normally no need to subclass Application.". I largely prefer sonxurxo's answer.

        – rds
        Mar 10 '11 at 16:41



















      7














      I going to contribute my approach to handling this rotation issue. This may not be relevant to OP as he's not using AsyncTask, but maybe others will find it useful. It's pretty simple but it seems to do the job for me:



      I have a login activity with a nested AsyncTask class called BackgroundLoginTask.



      In my BackgroundLoginTask I don't do anything out of the ordinary except to add a null check upon calling ProgressDialog's dismiss:



      @Override
      protected void onPostExecute(Boolean result)
      {
      if (pleaseWaitDialog != null)
      pleaseWaitDialog.dismiss();
      [...]
      }


      This is to handle the case where the background task finishes while the Activity is not visible and, therefore, the progress dialog has already been dismissed by the onPause() method.



      Next, in my parent Activity class, I create global static handles to my AsyncTask class and my ProgressDialog (the AsyncTask, being nested, can access these variables):



      private static BackgroundLoginTask backgroundLoginTask;
      private static ProgressDialog pleaseWaitDialog;


      This serves two purposes: First, it allows my Activity to always access the AsyncTask object even from a new, post-rotated activity. Second, it allows my BackgroundLoginTask to access and dismiss the ProgressDialog even after a rotate.



      Next, I add this to onPause(), causing the progress dialog to disappear when our Activity is leaving the foreground (preventing that ugly "force close" crash):



          if (pleaseWaitDialog != null)
      pleaseWaitDialog.dismiss();


      Finally, I have the following in my onResume() method:



      if ((backgroundLoginTask != null) && (backgroundLoginTask.getStatus() == Status.RUNNING))
      {
      if (pleaseWaitDialog != null)
      pleaseWaitDialog.show();
      }


      This allows the Dialog to reappear after the Activity is recreated.



      Here is the entire class:



      public class NSFkioskLoginActivity extends NSFkioskBaseActivity {
      private static BackgroundLoginTask backgroundLoginTask;
      private static ProgressDialog pleaseWaitDialog;
      private Controller cont;

      // This is the app entry point.
      /** Called when the activity is first created. */
      @Override
      public void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);

      if (CredentialsAvailableAndValidated())
      {
      //Go to main menu and don't run rest of onCreate method.
      gotoMainMenu();
      return;
      }
      setContentView(R.layout.login);
      populateStoredCredentials();
      }

      //Save current progress to options when app is leaving foreground
      @Override
      public void onPause()
      {
      super.onPause();
      saveCredentialsToPreferences(false);
      //Get rid of progress dialog in the event of a screen rotation. Prevents a crash.
      if (pleaseWaitDialog != null)
      pleaseWaitDialog.dismiss();
      }

      @Override
      public void onResume()
      {
      super.onResume();
      if ((backgroundLoginTask != null) && (backgroundLoginTask.getStatus() == Status.RUNNING))
      {
      if (pleaseWaitDialog != null)
      pleaseWaitDialog.show();
      }
      }

      /**
      * Go to main menu, finishing this activity
      */
      private void gotoMainMenu()
      {
      startActivity(new Intent(getApplicationContext(), NSFkioskMainMenuActivity.class));
      finish();
      }

      /**
      *
      * @param setValidatedBooleanTrue If set true, method will set CREDS_HAVE_BEEN_VALIDATED to true in addition to saving username/password.
      */
      private void saveCredentialsToPreferences(boolean setValidatedBooleanTrue)
      {
      SharedPreferences settings = getSharedPreferences(APP_PREFERENCES, MODE_PRIVATE);
      SharedPreferences.Editor prefEditor = settings.edit();
      EditText usernameText = (EditText) findViewById(R.id.editTextUsername);
      EditText pswText = (EditText) findViewById(R.id.editTextPassword);
      prefEditor.putString(USERNAME, usernameText.getText().toString());
      prefEditor.putString(PASSWORD, pswText.getText().toString());
      if (setValidatedBooleanTrue)
      prefEditor.putBoolean(CREDS_HAVE_BEEN_VALIDATED, true);
      prefEditor.commit();
      }

      /**
      * Checks if user is already signed in
      */
      private boolean CredentialsAvailableAndValidated() {
      SharedPreferences settings = getSharedPreferences(APP_PREFERENCES,
      MODE_PRIVATE);
      if (settings.contains(USERNAME) && settings.contains(PASSWORD) && settings.getBoolean(CREDS_HAVE_BEEN_VALIDATED, false) == true)
      return true;
      else
      return false;
      }

      //Populate stored credentials, if any available
      private void populateStoredCredentials()
      {
      SharedPreferences settings = getSharedPreferences(APP_PREFERENCES,
      MODE_PRIVATE);
      settings.getString(USERNAME, "");
      EditText usernameText = (EditText) findViewById(R.id.editTextUsername);
      usernameText.setText(settings.getString(USERNAME, ""));
      EditText pswText = (EditText) findViewById(R.id.editTextPassword);
      pswText.setText(settings.getString(PASSWORD, ""));
      }

      /**
      * Validate credentials in a seperate thread, displaying a progress circle in the meantime
      * If successful, save credentials in preferences and proceed to main menu activity
      * If not, display an error message
      */
      public void loginButtonClick(View view)
      {
      if (phoneIsOnline())
      {
      EditText usernameText = (EditText) findViewById(R.id.editTextUsername);
      EditText pswText = (EditText) findViewById(R.id.editTextPassword);
      //Call background task worker with username and password params
      backgroundLoginTask = new BackgroundLoginTask();
      backgroundLoginTask.execute(usernameText.getText().toString(), pswText.getText().toString());
      }
      else
      {
      //Display toast informing of no internet access
      String notOnlineMessage = getResources().getString(R.string.noNetworkAccessAvailable);
      Toast toast = Toast.makeText(getApplicationContext(), notOnlineMessage, Toast.LENGTH_SHORT);
      toast.show();
      }
      }

      /**
      *
      * Takes two params: username and password
      *
      */
      public class BackgroundLoginTask extends AsyncTask<Object, String, Boolean>
      {
      private Exception e = null;

      @Override
      protected void onPreExecute()
      {
      cont = Controller.getInstance();
      //Show progress dialog
      String pleaseWait = getResources().getString(R.string.pleaseWait);
      String commWithServer = getResources().getString(R.string.communicatingWithServer);
      if (pleaseWaitDialog == null)
      pleaseWaitDialog= ProgressDialog.show(NSFkioskLoginActivity.this, pleaseWait, commWithServer, true);

      }

      @Override
      protected Boolean doInBackground(Object... params)
      {
      try {
      //Returns true if credentials were valid. False if not. Exception if server could not be reached.
      return cont.validateCredentials((String)params[0], (String)params[1]);
      } catch (Exception e) {
      this.e=e;
      return false;
      }
      }

      /**
      * result is passed from doInBackground. Indicates whether credentials were validated.
      */
      @Override
      protected void onPostExecute(Boolean result)
      {
      //Hide progress dialog and handle exceptions
      //Progress dialog may be null if rotation has been switched
      if (pleaseWaitDialog != null)
      {
      pleaseWaitDialog.dismiss();
      pleaseWaitDialog = null;
      }

      if (e != null)
      {
      //Show toast with exception text
      String networkError = getResources().getString(R.string.serverErrorException);
      Toast toast = Toast.makeText(getApplicationContext(), networkError, Toast.LENGTH_SHORT);
      toast.show();
      }
      else
      {
      if (result == true)
      {
      saveCredentialsToPreferences(true);
      gotoMainMenu();
      }
      else
      {
      String toastText = getResources().getString(R.string.invalidCredentialsEntered);
      Toast toast = Toast.makeText(getApplicationContext(), toastText, Toast.LENGTH_SHORT);
      toast.show();
      }
      }
      }

      }
      }


      I am by no means a seasoned Android developer, so feel free to comment.






      share|improve this answer





















      • 1





        Interesting! Especially for those of us using AsyncTask. Just tried out your solution, and it seems to mostly work. There's one problem: the ProgressDialog seems to terminate a little early after a rotation WHILE the ProgressDialog is still active. I'm going to play around to see exactly what's happening and how to remedy it. But I'm no longer getting those crashes!

        – Scott Biggs
        Feb 7 '12 at 7:00






      • 1





        Found a fix. It seems that the problem here is the static ProgressDialog. When rotations interrupt the ProgressDialog, it sometimes gets its .dismiss() method called after it is restarted in the new Activity. By making the ProgressDialog created with each Activity, we ensure that this new ProgressDialog isn't killed along with the old Activity. I also made sure that the ProgressDialog is set to null whenever it's dismissed (to aid garbage collection). So we have a solution here! Cheers to those using AsyncTask!

        – Scott Biggs
        Feb 8 '12 at 6:06



















      4














      Move the long task to a seperate class. Implement it as a subject-observer pattern. Whenever the activity is created register and while closing unregister with the task class. Task class can use AsyncTask.






      share|improve this answer



















      • 1





        I don't see how that would help. Could you explain in more detail how this prevents the problems I am seeing.

        – Heikki Toivonen
        Jul 11 '09 at 17:14






      • 1





        As Haseman said it prevents the backend to access the UI elements and we can seperate the UI from backend, backend runs in seperate thread and it continues to run even after the screen is re-oriented and Register-UnRegister with the Backend task for status updates. The real example I have solved using this is that I have a Download Task, I have moved that to a seperate thread, whenever the thread is created I register-unregister with it.

        – Vinay
        Jul 14 '09 at 17:17











      • Ok, I am revisiting this issue and I don't think I still fully understand this answer. Suppose we have the main activity start an AsyncTask to do a long-running network operation we don't want to interrupt during screen orientation change. I don't see how the new activity can send a message to the AsyncTask started by the old activity. Can you give a code example?

        – Heikki Toivonen
        May 7 '10 at 7:54













      • @Heikki, is my implementation below what you mean?

        – beetstra
        Apr 29 '11 at 13:58



















      4














      The trick is to show/dismiss the dialog within AsyncTask during onPreExecute/onPostExecute as usual, though in case of orientation-change create/show a new instance of the dialog in the activity and pass its reference to the task.



      public class MainActivity extends Activity {
      private Button mButton;
      private MyTask mTask = null;

      @Override
      public void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.main);

      MyTask task = (MyTask) getLastNonConfigurationInstance();
      if(task != null){
      mTask = task;
      mTask.mContext = this;
      mTask.mDialog = ProgressDialog.show(this, "", "", true);
      }

      mButton = (Button) findViewById(R.id.button1);
      mButton.setOnClickListener(new View.OnClickListener(){
      public void onClick(View v){
      mTask = new MyTask(MainActivity.this);
      mTask.execute();
      }
      });
      }


      @Override
      public Object onRetainNonConfigurationInstance() {
      String str = "null";
      if(mTask != null){
      str = mTask.toString();
      mTask.mDialog.dismiss();
      }
      Toast.makeText(this, str, Toast.LENGTH_SHORT).show();
      return mTask;
      }



      private class MyTask extends AsyncTask<Void, Void, Void>{
      private ProgressDialog mDialog;
      private MainActivity mContext;


      public MyTask(MainActivity context){
      super();
      mContext = context;
      }


      protected void onPreExecute() {
      mDialog = ProgressDialog.show(MainActivity.this, "", "", true);
      }

      protected void onPostExecute(Void result) {
      mContext.mTask = null;
      mDialog.dismiss();
      }


      @Override
      protected Void doInBackground(Void... params) {
      SystemClock.sleep(5000);
      return null;
      }
      }
      }





      share|improve this answer

































        4














        I have done it like this:



            package com.palewar;
        import android.app.Activity;
        import android.app.ProgressDialog;
        import android.os.Bundle;
        import android.os.Handler;
        import android.os.Message;

        public class ThreadActivity extends Activity {


        static ProgressDialog dialog;
        private Thread downloadThread;
        final static Handler handler = new Handler() {

        @Override
        public void handleMessage(Message msg) {

        super.handleMessage(msg);

        dialog.dismiss();

        }

        };

        protected void onDestroy() {
        super.onDestroy();
        if (dialog != null && dialog.isShowing()) {
        dialog.dismiss();
        dialog = null;
        }

        }

        /** Called when the activity is first created. */
        @Override
        public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        downloadThread = (Thread) getLastNonConfigurationInstance();
        if (downloadThread != null && downloadThread.isAlive()) {
        dialog = ProgressDialog.show(ThreadActivity.this, "",
        "Signing in...", false);
        }

        dialog = ProgressDialog.show(ThreadActivity.this, "",
        "Signing in ...", false);

        downloadThread = new MyThread();
        downloadThread.start();
        // processThread();
        }

        // Save the thread
        @Override
        public Object onRetainNonConfigurationInstance() {
        return downloadThread;
        }


        static public class MyThread extends Thread {
        @Override
        public void run() {

        try {
        // Simulate a slow network
        try {
        new Thread().sleep(5000);
        } catch (InterruptedException e) {
        e.printStackTrace();
        }
        handler.sendEmptyMessage(0);

        } finally {

        }
        }
        }

        }


        You can also try and let me know it works for you or not






        share|improve this answer


























        • The onDestroy code may not be executed at all, from Developer's page: "Note the "Killable" column in the above table -- for those methods that are marked as being killable, after that method returns the process hosting the activity may killed by the system at any time without another line of its code being executed"

          – ilomambo
          May 5 '12 at 8:21













        • I firmly believe that "onRetainNonConfigurationInstance()" is the method to be used for such cases...nyc work

          – Nitin Bansal
          Aug 21 '12 at 4:04











        • I am facing similar problem, as Sachin Gurnani does I using static declaration to fix my problem. stackoverflow.com/questions/12058774/…

          – Steven Du
          Aug 22 '12 at 1:32





















        2














        If you create a background Service that does all the heavy lifting (tcp requests/response, unmarshalling), the View and Activity can be destroyed and re-created without leaking window or losing data. This allows the Android recommended behavior, which is to destroy an Activity on each configuration change (eg. for each orientation change).



        It is a bit more complex, but it is the best way for invoking server request, data pre/post-processing, etc.



        You may even use your Service to queue each request to a server, so it makes it easy and efficient to handle those things.



        The dev guide has a full chapter on Services.






        share|improve this answer


























        • A Service is more work than an AsyncTask but can be a better approach in some situations. It is not necessarily better, is it? That being said, I don't understand how this solves the problem of the ProgressDialog that is leaked from the main Activity. Where do you instanciate the ProgressDialog? Where do you dismiss it?

          – rds
          Mar 10 '11 at 18:12



















        2














        I have an implementation which allows the activity to be destroyed on a screen orientation change, but still destroys the dialog in the recreated activity successfully.
        I use ...NonConfigurationInstance to attach the background task to the recreated activity.
        The normal Android framework handles recreating the dialog itself, nothing is changed there.



        I subclassed AsyncTask adding a field for the 'owning' activity, and a method to update this owner.



        class MyBackgroundTask extends AsyncTask<...> {
        MyBackgroundTask (Activity a, ...) {
        super();
        this.ownerActivity = a;
        }

        public void attach(Activity a) {
        ownerActivity = a;
        }

        protected void onPostExecute(Integer result) {
        super.onPostExecute(result);
        ownerActivity.dismissDialog(DIALOG_PROGRESS);
        }

        ...
        }


        In my activity class I added a field backgroundTask referring to the 'owned' backgroundtask, and I update this field using onRetainNonConfigurationInstance and getLastNonConfigurationInstance.



        class MyActivity extends Activity {
        public void onCreate(Bundle savedInstanceState) {
        ...
        if (getLastNonConfigurationInstance() != null) {
        backgroundTask = (MyBackgroundTask) getLastNonConfigurationInstance();
        backgroundTask.attach(this);
        }
        }

        void startBackgroundTask() {
        backgroundTask = new MyBackgroundTask(this, ...);
        showDialog(DIALOG_PROGRESS);
        backgroundTask.execute(...);
        }

        public Object onRetainNonConfigurationInstance() {
        if (backgroundTask != null && backgroundTask.getStatus() != Status.FINISHED)
        return backgroundTask;
        return null;
        }
        ...
        }


        Suggestions for further improvement:




        • Clear the backgroundTask reference in the activity after the task is finished to release any memory or other resources associated with it.

        • Clear the ownerActivity reference in the backgroundtask before the activity is destroyed in case it will not be recreated immediately.

        • Create a BackgroundTask interface and/or collection to allow different types of tasks to run from the same owning activity.






        share|improve this answer































          2














          If you maintain two layouts, all UI thread should be terminated.



          If you use AsynTask, then you can easily call .cancel() method inside onDestroy() method of current activity.



          @Override
          protected void onDestroy (){
          removeDialog(DIALOG_LOGIN_ID); // remove loading dialog
          if (loginTask != null){
          if (loginTask.getStatus() != AsyncTask.Status.FINISHED)
          loginTask.cancel(true); //cancel AsyncTask
          }
          super.onDestroy();
          }


          For AsyncTask, read more in "Cancelling a task" section at here.



          Update:
          Added condition to check status, as it can be only cancelled if it is in running state.
          Also note that the AsyncTask can only be executed one time.






          share|improve this answer

































            2














            Tried to implement jfelectron's solution because it is a "rock-solid solution to these issues that conforms with the 'Android Way' of things" but it took some time to look up and put together all the elements mentioned. Ended up with this slightly different, and I think more elegant, solution posted here in it's entirety.



            Uses an IntentService fired from an activity to perform the long running task on a separate thread. The service fires back sticky Broadcast Intents to the activity which update the dialog. The Activity uses showDialog(), onCreateDialog() and onPrepareDialog() to eliminate the need to have persistent data passed in the application object or the savedInstanceState bundle. This should work no matter how your application is interrupted.



            Activity Class:



            public class TesterActivity extends Activity {
            private ProgressDialog mProgressDialog;
            private static final int PROGRESS_DIALOG = 0;

            @Override
            public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);

            Button b = (Button) this.findViewById(R.id.test_button);
            b.setOnClickListener(new OnClickListener() {
            public void onClick(View v) {
            buttonClick();
            }
            });
            }

            private void buttonClick(){
            clearPriorBroadcast();
            showDialog(PROGRESS_DIALOG);
            Intent svc = new Intent(this, MyService.class);
            startService(svc);
            }

            protected Dialog onCreateDialog(int id) {
            switch(id) {
            case PROGRESS_DIALOG:
            mProgressDialog = new ProgressDialog(TesterActivity.this);
            mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
            mProgressDialog.setMax(MyService.MAX_COUNTER);
            mProgressDialog.setMessage("Processing...");
            return mProgressDialog;
            default:
            return null;
            }
            }

            @Override
            protected void onPrepareDialog(int id, Dialog dialog) {
            switch(id) {
            case PROGRESS_DIALOG:
            // setup a broadcast receiver to receive update events from the long running process
            IntentFilter filter = new IntentFilter();
            filter.addAction(MyService.BG_PROCESS_INTENT);
            registerReceiver(new MyBroadcastReceiver(), filter);
            break;
            }
            }

            public class MyBroadcastReceiver extends BroadcastReceiver{
            @Override
            public void onReceive(Context context, Intent intent) {
            if (intent.hasExtra(MyService.KEY_COUNTER)){
            int count = intent.getIntExtra(MyService.KEY_COUNTER, 0);
            mProgressDialog.setProgress(count);
            if (count >= MyService.MAX_COUNTER){
            dismissDialog(PROGRESS_DIALOG);
            }
            }
            }
            }

            /*
            * Sticky broadcasts persist and any prior broadcast will trigger in the
            * broadcast receiver as soon as it is registered.
            * To clear any prior broadcast this code sends a blank broadcast to clear
            * the last sticky broadcast.
            * This broadcast has no extras it will be ignored in the broadcast receiver
            * setup in onPrepareDialog()
            */
            private void clearPriorBroadcast(){
            Intent broadcastIntent = new Intent();
            broadcastIntent.setAction(MyService.BG_PROCESS_INTENT);
            sendStickyBroadcast(broadcastIntent);
            }}


            IntentService Class:



            public class MyService extends IntentService {

            public static final String BG_PROCESS_INTENT = "com.mindspiker.Tester.MyService.TEST";
            public static final String KEY_COUNTER = "counter";
            public static final int MAX_COUNTER = 100;

            public MyService() {
            super("");
            }

            @Override
            protected void onHandleIntent(Intent intent) {
            for (int i = 0; i <= MAX_COUNTER; i++) {
            Log.e("Service Example", " " + i);
            try {
            Thread.sleep(100);
            } catch (InterruptedException e) {
            e.printStackTrace();
            }

            Intent broadcastIntent = new Intent();
            broadcastIntent.setAction(BG_PROCESS_INTENT);
            broadcastIntent.putExtra(KEY_COUNTER, i);
            sendStickyBroadcast(broadcastIntent);
            }
            }}


            Manifest file entries:



            before application section:



            uses-permission android:name="com.mindspiker.Tester.MyService.TEST"
            uses-permission android:name="android.permission.BROADCAST_STICKY"


            inside application section



            service android:name=".MyService"





            share|improve this answer

































              2














              This is my proposed solution:




              • Move the AsyncTask or Thread to a retained Fragment, as explained here. I believe it is a good practice to move all network calls to fragments. If you are already using fragments, one of them could be made responsible for the calls. Otherwise, you can create a fragment just for doing the request, as the linked article proposes.

              • The fragment will use a listener interface to signal the task completion/failure. You don't have to worry for orientation changes there. The fragment will always have the correct link to the current activity and progress dialog can be safely resumed.

              • Make your progress dialog a member of your class. In fact you should do that for all dialogs. In the onPause method you should dismiss them, otherwise you will leak a window on the configuration change. The busy state should be kept by the fragment. When the fragment is attached to the activity, you can bring up the progress dialog again, if the call is still running. A void showProgressDialog() method can be added to the fragment-activity listener interface for this purpose.






              share|improve this answer


























              • Perfect solution, but don't understand why this answer is overshadowed from others !!!

                – blackkara
                Feb 28 '17 at 3:18



















              1














              I've tried EVERYTHING. Spent days experimenting. I didn't want to block the activity from rotating. My scenario was:




              1. A progress dialog showing dynamic information to the user. E.g.: "Connecting to server...", "Downloading data...", etc.

              2. A thread doing the heavy stuff and updating the dialog

              3. Updating the UI with the results at the end.


              The problem was, when rotating the screen, every solution on the book failed. Even with the AsyncTask class, which is the correct Android way of dealing with this situations. When rotating the screen, the current Context that the starting thread is working with, is gone, and that messes up with the dialog that is showing. The problem was always the Dialog, no matter how many tricks I added to the code (passing new contexts to running threads, retaining thread states through rotations, etc...). The code complexity at the end was always huge and there was always something that could go wrong.



              The only solution that worked for me was the Activity/Dialog trick. It's simple and genius and it's all rotation proof:




              1. Instead of creating a Dialog and ask to show it, create an Activity that has been set in the manifest with android:theme="@android:style/Theme.Dialog". So, it just looks like a dialog.


              2. Replace showDialog(DIALOG_ID) with startActivityForResult(yourActivityDialog, yourCode);


              3. Use onActivityResult in the calling Activity to get the results from the executing thread (even the errors) and update the UI.


              4. On your 'ActivityDialog', use threads or AsyncTask to execute long tasks and onRetainNonConfigurationInstance to save "dialog" state when rotating the screen.



              This is fast and works fine. I still use dialogs for other tasks and the AsyncTask for something that doesn't require a constant dialog on screen. But with this scenario, I always go for the Activity/Dialog pattern.



              And, I didn't try it, but it's even possible to block that Activity/Dialog from rotating, when the thread is running, speeding things up, while allowing the calling Activity to rotate.






              share|improve this answer
























              • Nice except that parameters must be passed through an Intent, which is more restrictive than the Object allowed by AsyncTask

                – rds
                Mar 29 '11 at 21:24











              • @Rui I too used this method for the last year. It has now occurred to me though that this is also incorrect. Why would Google even have a Dialog if this was the way to 'fix' this issue? The problem I see is that if you open ActivityB (Theme.Dialog) from ActivityA then ActivityA is moved down on the Activity stack thus is marked as ready to kill by the OS if necessary. Therefore, if you have a long running process and are showing some sort of faux progress 'dialog' and it took too long and memory ran low... ActivityA is killed and there is nothing to come back too upon progress complete.

                – rf43
                Oct 13 '11 at 0:47





















              1














              These days there is a much more distinct way to handle these types of issues. The typical approach is:



              1. Ensure your data is properly seperated from the UI:



              Anything that is a background process should be in a retained Fragment (set this with Fragment.setRetainInstance(). This becomes your 'persistent data storage' where anything data based that you would like retained is kept. After the orientation change event, this Fragment will still be accessible in its original state through a FragmentManager.findFragmentByTag() call (when you create it you should give it a tag not an ID as it is not attached to a View).



              See the Handling Runtime Changes developed guide for information about doing this correctly and why it is the best option.



              2. Ensure you are interfacing correctly and safely between the background processs and your UI:



              You must reverse your linking process. At the moment your background process attaches itself to a View - instead your View should be attaching itself to the background process. It makes more sense right? The View's action is dependent on the background process, whereas the background process is not dependent on the View.This means changing the link to a standard Listener interface. Say your process (whatever class it is - whether it is an AsyncTask, Runnable or whatever) defines a OnProcessFinishedListener, when the process is done it should call that listener if it exists.



              This answer is a nice concise description of how to do custom listeners.



              3. Link your UI into the data process whenever the UI is created (including orientation changes):



              Now you must worry about interfacing the background task with whatever your current View structure is. If you are handling your orientation changes properly (not the configChanges hack people always recommend), then your Dialog will be recreated by the system. This is important, it means that on the orientation change, all your Dialog's lifecycle methods are recalled. So in any of these methods (onCreateDialog is usually a good place), you could do a call like the following:





              DataFragment f = getActivity().getFragmentManager().findFragmentByTag("BACKGROUND_TAG");
              if (f != null) {
              f.mBackgroundProcess.setOnProcessFinishedListener(new OnProcessFinishedListener() {
              public void onProcessFinished() {
              dismiss();
              }
              });
              }


              See the Fragment lifecycle for deciding where setting the listener best fits in your individual implementation.





              This is a general approach to providing a robust and complete solution to the generic problem asked in this question. There is probably a few minor pieces missing in this answer depending on your individual scenario, but this is generally the most correct approach for properly handling orientation change events.






              share|improve this answer

































                1














                I faced the same situation. What I did was get only one instance for my progress dialog in the entire application.



                First, I created a DialogSingleton class to get only one instance (Singleton pattern)



                public class DialogSingleton
                {
                private static Dialog dialog;

                private static final Object mLock = new Object();
                private static DialogSingleton instance;

                private DialogSingleton()
                {

                }

                public static DialogSingleton GetInstance()
                {
                synchronized (mLock)
                {
                if(instance == null)
                {
                instance = new DialogSingleton();
                }

                return instance;
                }
                }

                public void DialogShow(Context context, String title)
                {
                if(!((Activity)context).isFinishing())
                {
                dialog = new ProgressDialog(context, 2);

                dialog.setCanceledOnTouchOutside(false);

                dialog.setTitle(title);

                dialog.show();
                }
                }

                public void DialogDismiss(Context context)
                {
                if(!((Activity)context).isFinishing() && dialog.isShowing())
                {
                dialog.dismiss();
                }
                }
                }


                As I show in this class, I have the progress dialog as attribute. Every time I need to show a progress dialog, I get the unique instance and create a new ProgressDialog.



                DialogSingleton.GetInstance().DialogShow(this, "My title here!");


                When I am done with the background task, I call again the unique instance and dismiss its dialog.



                DialogSingleton.GetInstance().DialogDismiss(this);


                I save the background task status in my shared preferences. When I rotate the screen, I ask if I have a task running for this activity: (onCreate)



                if(Boolean.parseBoolean(preference.GetValue(IS_TASK_NAME_EXECUTED_KEY, "boolean").toString()))
                {
                DialogSingleton.GetInstance().DialogShow(this, "Checking credentials!");
                } // preference object gets the info from shared preferences (my own implementation to get and put data to shared preferences) and IS_TASK_NAME_EXECUTED_KEY is the key to save this flag (flag to know if this activity has a background task already running).


                When I start running a background task:



                preference.AddValue(IS_TASK_NAME_EXECUTED_KEY, true, "boolean");

                DialogSingleton.GetInstance().DialogShow(this, "My title here!");


                When I finish running a background task:



                preference.AddValue(IS_TASK_NAME_EXECUTED_KEY, false, "boolean");

                DialogSingleton.GetInstance().DialogDismiss(ActivityName.this);


                I hope it helps.






                share|improve this answer

































                  1














                  This is a very old question that came up on the sidebar for some reason.



                  If the background task only needs to survive while the activity is in the foreground, the "new" solution is to host the background thread (or, preferably, AsyncTask) in a retained fragment, as described in this developer guide and numerous Q&As.



                  A retained fragment survives if the activity is destroyed for a configuration change, but not when the activity is destroyed in the background or back stack. Therefore, the background task should still be interrupted if isChangingConfigurations() is false in onPause().






                  share|improve this answer

































                    1














                    I am a fresher in android and I tried this and it's worked.



                    public class loadTotalMemberByBranch extends AsyncTask<Void, Void,Void> {
                    ProgressDialog progressDialog = new ProgressDialog(Login.this);
                    int ranSucess=0;
                    @Override
                    protected void onPreExecute() {
                    // TODO Auto-generated method stub
                    super.onPreExecute();
                    progressDialog.setTitle("");
                    progressDialog.isIndeterminate();
                    progressDialog.setCancelable(false);
                    progressDialog.show();
                    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR);

                    }
                    @Override
                    protected Void doInBackground(Void... params) {
                    // TODO Auto-generated method stub

                    return null;
                    }
                    @Override
                    protected void onPostExecute(Void result) {
                    // TODO Auto-generated method stub
                    super.onPostExecute(result);
                    progressDialog.dismiss();
                    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR);
                    }
                    }





                    share|improve this answer

































                      0














                      Seems far too 'quick and dirty' to be true so please point out the flaws but what I found worked was...



                      Within the onPostExecute method of my AsyncTask, I simply wrapped the '.dismiss' for the progress dialog in a try/catch block (with an empty catch) and then simply ignored the exception that was raised. Seems wrong to do but appears there are no ill effects (at least for what I am doing subsequently which is to start another activity passing in the result of my long running query as an Extra)






                      share|improve this answer
























                      • Are-you saying there is actually no memory leak when the Android platforms tells the window is leaked?

                        – rds
                        Mar 10 '11 at 18:09











                      • My progress dialog is a member variable of the activity class so I assumed that when the activity is destroyed and recreated it will be garbage collected and there is no leak. Am I wrong?

                        – Simon
                        Mar 28 '11 at 20:01











                      • Yes, I think it's wrong. As you say, the Activity has a reference to the Dialog. When the configuration is changed, the first Activity is destroyed, which means all fields are set to null. But the low-level WindowManager also has a reference to the Dialog (since it is has not been dismissed yet). The new Activity tries to create a new Dialog (in preExecute()) and the window manager raises a fatal exception preventing you from doing so. Indeed, if it does so, there would be no way to cleanly destroy the Dialog hence keeping a reference to the initial Activity. Am I right?

                        – rds
                        Mar 29 '11 at 21:20



















                      0














                      The simplest and most flexible solution is to use an AsyncTask with a static reference to ProgressBar. This provides an encapsulated and thus reusable solution to orientation change problems. This solution has served me well for varying asyncronous tasks including internet downloads, communicating with Services, and filesystem scans. The solution has been well tested on multiple android versions and phone models. A complete demo can be found here with specific interest in DownloadFile.java



                      I present the following as a concept example



                      public class SimpleAsync extends AsyncTask<String, Integer, String> {
                      private static ProgressDialog mProgressDialog = null;
                      private final Context mContext;

                      public SimpleAsync(Context context) {
                      mContext = context;
                      if ( mProgressDialog != null ) {
                      onPreExecute();
                      }
                      }

                      @Override
                      protected void onPreExecute() {
                      mProgressDialog = new ProgressDialog( mContext );
                      mProgressDialog.show();
                      }

                      @Override
                      protected void onPostExecute(String result) {
                      if ( mProgressDialog != null ) {
                      mProgressDialog.dismiss();
                      mProgressDialog = null;
                      }
                      }

                      @Override
                      protected void onProgressUpdate(Integer... progress) {
                      mProgressDialog.setProgress( progress[0] );
                      }

                      @Override
                      protected String doInBackground(String... sUrl) {
                      // Do some work here
                      publishProgress(1);
                      return null;
                      }

                      public void dismiss() {
                      if ( mProgressDialog != null ) {
                      mProgressDialog.dismiss();
                      }
                      }
                      }


                      Usage in an Android Activity is simple



                      public class MainActivity extends Activity {
                      DemoServiceClient mClient = null;
                      DownloadFile mDownloadFile = null;

                      @Override
                      public void onCreate(Bundle savedInstanceState) {
                      super.onCreate( savedInstanceState );
                      setContentView( R.layout.main );
                      mDownloadFile = new DownloadFile( this );

                      Button downloadButton = (Button) findViewById( R.id.download_file_button );
                      downloadButton.setOnClickListener( new View.OnClickListener() {
                      @Override
                      public void onClick(View view) {
                      mDownloadFile.execute( "http://www.textfiles.com/food/bakebred.txt");
                      }
                      });
                      }

                      @Override
                      public void onPause() {
                      super.onPause();
                      mDownloadFile.dismiss();
                      }
                      }





                      share|improve this answer































                        0














                        i have found and easier solution to handle threads when orientation change. You can just keep an static reference to your activity/fragment and verify if its null before acting on the ui. I suggest using a try catch too:



                         public class DashListFragment extends Fragment {
                        private static DashListFragment ACTIVE_INSTANCE;

                        @Override
                        public void onCreate(Bundle savedInstanceState) {
                        super.onCreate(savedInstanceState);

                        ACTIVE_INSTANCE = this;

                        new Handler().postDelayed(new Runnable() {
                        public void run() {
                        try {
                        if (ACTIVE_INSTANCE != null) {
                        setAdapter(); // this method do something on ui or use context
                        }
                        }
                        catch (Exception e) {}


                        }
                        }, 1500l);

                        }

                        @Override
                        public void onDestroy() {
                        super.onDestroy();

                        ACTIVE_INSTANCE = null;
                        }


                        }





                        share|improve this answer































                          0














                          If you're struggling with detecting orientation change events of a dialog INDEPENDENT OF AN ACTIVITY REFERENCE, this method works excitingly well. I use this because I have my own dialog class that can be shown in multiple different Activities so I don't always know which Activity it's being shown in. With this method you don't need to change the AndroidManifest, worry about Activity references, and you don't need a custom dialog (as I have). You do need, however, a custom content view so you can detect the orientation changes using that particular view. Here's my example:



                          Setup



                          public class MyContentView extends View{
                          public MyContentView(Context context){
                          super(context);
                          }

                          @Override
                          public void onConfigurationChanged(Configuration newConfig){
                          super.onConfigurationChanged(newConfig);

                          //DO SOMETHING HERE!! :D
                          }
                          }


                          Implementation 1 - Dialog



                          Dialog dialog = new Dialog(context);
                          //set up dialog
                          dialog.setContentView(new MyContentView(context));
                          dialog.show();


                          Implementation 2 - AlertDialog.Builder



                          AlertDialog.Builder builder = new AlertDialog.Builder(context);
                          //set up dialog builder
                          builder.setView(new MyContentView(context)); //Can use this method
                          builder.setCustomTitle(new MycontentView(context)); // or this method
                          builder.build().show();


                          Implementation 3 - ProgressDialog / AlertDialog



                          ProgressDialog progress = new ProgressDialog(context);
                          //set up progress dialog
                          progress.setView(new MyContentView(context)); //Can use this method
                          progress.setCustomTitle(new MyContentView(context)); // or this method
                          progress.show();





                          share|improve this answer






















                            protected by Tim Post Feb 25 '11 at 11:04



                            Thank you for your interest in this question.
                            Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).



                            Would you like to answer one of these unanswered questions instead?














                            26 Answers
                            26






                            active

                            oldest

                            votes








                            26 Answers
                            26






                            active

                            oldest

                            votes









                            active

                            oldest

                            votes






                            active

                            oldest

                            votes









                            146














                            When you switch orientations, Android will create a new View. You're probably getting crashes because your background thread is trying to change the state on the old one. (It may also be having trouble because your background thread isn't on the UI thread)



                            I'd suggest making that mHandler volatile and updating it when the orientation changes.






                            share|improve this answer



















                            • 13





                              You might have pinpointed the reason for the crash. I got rid of the crash, but I still haven't figured out how to restore the UI to the state it was in before the orientation change in a reliable way. But your answer moved me forward, so awarding it as answer.

                              – Heikki Toivonen
                              Jul 13 '09 at 4:35






                            • 4





                              You should get an onStart in your activity when the orientation changes. Essentially, you have to reconfigure the view using the old data. So I'd suggest requesting numerical status udpates from the progress bar and rebuilding a new view when you get that new 'onStart' I can't remember offhand if you get a new activity as well but some hunting through the documentation should help.

                              – haseman
                              Jul 13 '09 at 18:31






                            • 6





                              Having played with it recently, I can pass on that you do get a new activity when your app changes orientation. (You also get a new view) If you try to update the old view you'll get an exception because the old view has an invalid application context (your old activity) You can kinda get around this by passing in myActivity.getApplicationContext() instead of a pointer to the activity itself.

                              – haseman
                              Jul 30 '09 at 21:35






                            • 1





                              Can someone explain the usage/benefit of volatile in this context

                              – Xar E Ahmer
                              Apr 28 '15 at 10:50






                            • 2





                              @Nepster Yeah I was wondering about that, too. It would be great if someone explained about the volatile.

                              – RestInPeace
                              May 2 '15 at 5:27
















                            146














                            When you switch orientations, Android will create a new View. You're probably getting crashes because your background thread is trying to change the state on the old one. (It may also be having trouble because your background thread isn't on the UI thread)



                            I'd suggest making that mHandler volatile and updating it when the orientation changes.






                            share|improve this answer



















                            • 13





                              You might have pinpointed the reason for the crash. I got rid of the crash, but I still haven't figured out how to restore the UI to the state it was in before the orientation change in a reliable way. But your answer moved me forward, so awarding it as answer.

                              – Heikki Toivonen
                              Jul 13 '09 at 4:35






                            • 4





                              You should get an onStart in your activity when the orientation changes. Essentially, you have to reconfigure the view using the old data. So I'd suggest requesting numerical status udpates from the progress bar and rebuilding a new view when you get that new 'onStart' I can't remember offhand if you get a new activity as well but some hunting through the documentation should help.

                              – haseman
                              Jul 13 '09 at 18:31






                            • 6





                              Having played with it recently, I can pass on that you do get a new activity when your app changes orientation. (You also get a new view) If you try to update the old view you'll get an exception because the old view has an invalid application context (your old activity) You can kinda get around this by passing in myActivity.getApplicationContext() instead of a pointer to the activity itself.

                              – haseman
                              Jul 30 '09 at 21:35






                            • 1





                              Can someone explain the usage/benefit of volatile in this context

                              – Xar E Ahmer
                              Apr 28 '15 at 10:50






                            • 2





                              @Nepster Yeah I was wondering about that, too. It would be great if someone explained about the volatile.

                              – RestInPeace
                              May 2 '15 at 5:27














                            146












                            146








                            146







                            When you switch orientations, Android will create a new View. You're probably getting crashes because your background thread is trying to change the state on the old one. (It may also be having trouble because your background thread isn't on the UI thread)



                            I'd suggest making that mHandler volatile and updating it when the orientation changes.






                            share|improve this answer













                            When you switch orientations, Android will create a new View. You're probably getting crashes because your background thread is trying to change the state on the old one. (It may also be having trouble because your background thread isn't on the UI thread)



                            I'd suggest making that mHandler volatile and updating it when the orientation changes.







                            share|improve this answer












                            share|improve this answer



                            share|improve this answer










                            answered Jul 12 '09 at 19:34









                            hasemanhaseman

                            9,32083538




                            9,32083538








                            • 13





                              You might have pinpointed the reason for the crash. I got rid of the crash, but I still haven't figured out how to restore the UI to the state it was in before the orientation change in a reliable way. But your answer moved me forward, so awarding it as answer.

                              – Heikki Toivonen
                              Jul 13 '09 at 4:35






                            • 4





                              You should get an onStart in your activity when the orientation changes. Essentially, you have to reconfigure the view using the old data. So I'd suggest requesting numerical status udpates from the progress bar and rebuilding a new view when you get that new 'onStart' I can't remember offhand if you get a new activity as well but some hunting through the documentation should help.

                              – haseman
                              Jul 13 '09 at 18:31






                            • 6





                              Having played with it recently, I can pass on that you do get a new activity when your app changes orientation. (You also get a new view) If you try to update the old view you'll get an exception because the old view has an invalid application context (your old activity) You can kinda get around this by passing in myActivity.getApplicationContext() instead of a pointer to the activity itself.

                              – haseman
                              Jul 30 '09 at 21:35






                            • 1





                              Can someone explain the usage/benefit of volatile in this context

                              – Xar E Ahmer
                              Apr 28 '15 at 10:50






                            • 2





                              @Nepster Yeah I was wondering about that, too. It would be great if someone explained about the volatile.

                              – RestInPeace
                              May 2 '15 at 5:27














                            • 13





                              You might have pinpointed the reason for the crash. I got rid of the crash, but I still haven't figured out how to restore the UI to the state it was in before the orientation change in a reliable way. But your answer moved me forward, so awarding it as answer.

                              – Heikki Toivonen
                              Jul 13 '09 at 4:35






                            • 4





                              You should get an onStart in your activity when the orientation changes. Essentially, you have to reconfigure the view using the old data. So I'd suggest requesting numerical status udpates from the progress bar and rebuilding a new view when you get that new 'onStart' I can't remember offhand if you get a new activity as well but some hunting through the documentation should help.

                              – haseman
                              Jul 13 '09 at 18:31






                            • 6





                              Having played with it recently, I can pass on that you do get a new activity when your app changes orientation. (You also get a new view) If you try to update the old view you'll get an exception because the old view has an invalid application context (your old activity) You can kinda get around this by passing in myActivity.getApplicationContext() instead of a pointer to the activity itself.

                              – haseman
                              Jul 30 '09 at 21:35






                            • 1





                              Can someone explain the usage/benefit of volatile in this context

                              – Xar E Ahmer
                              Apr 28 '15 at 10:50






                            • 2





                              @Nepster Yeah I was wondering about that, too. It would be great if someone explained about the volatile.

                              – RestInPeace
                              May 2 '15 at 5:27








                            13




                            13





                            You might have pinpointed the reason for the crash. I got rid of the crash, but I still haven't figured out how to restore the UI to the state it was in before the orientation change in a reliable way. But your answer moved me forward, so awarding it as answer.

                            – Heikki Toivonen
                            Jul 13 '09 at 4:35





                            You might have pinpointed the reason for the crash. I got rid of the crash, but I still haven't figured out how to restore the UI to the state it was in before the orientation change in a reliable way. But your answer moved me forward, so awarding it as answer.

                            – Heikki Toivonen
                            Jul 13 '09 at 4:35




                            4




                            4





                            You should get an onStart in your activity when the orientation changes. Essentially, you have to reconfigure the view using the old data. So I'd suggest requesting numerical status udpates from the progress bar and rebuilding a new view when you get that new 'onStart' I can't remember offhand if you get a new activity as well but some hunting through the documentation should help.

                            – haseman
                            Jul 13 '09 at 18:31





                            You should get an onStart in your activity when the orientation changes. Essentially, you have to reconfigure the view using the old data. So I'd suggest requesting numerical status udpates from the progress bar and rebuilding a new view when you get that new 'onStart' I can't remember offhand if you get a new activity as well but some hunting through the documentation should help.

                            – haseman
                            Jul 13 '09 at 18:31




                            6




                            6





                            Having played with it recently, I can pass on that you do get a new activity when your app changes orientation. (You also get a new view) If you try to update the old view you'll get an exception because the old view has an invalid application context (your old activity) You can kinda get around this by passing in myActivity.getApplicationContext() instead of a pointer to the activity itself.

                            – haseman
                            Jul 30 '09 at 21:35





                            Having played with it recently, I can pass on that you do get a new activity when your app changes orientation. (You also get a new view) If you try to update the old view you'll get an exception because the old view has an invalid application context (your old activity) You can kinda get around this by passing in myActivity.getApplicationContext() instead of a pointer to the activity itself.

                            – haseman
                            Jul 30 '09 at 21:35




                            1




                            1





                            Can someone explain the usage/benefit of volatile in this context

                            – Xar E Ahmer
                            Apr 28 '15 at 10:50





                            Can someone explain the usage/benefit of volatile in this context

                            – Xar E Ahmer
                            Apr 28 '15 at 10:50




                            2




                            2





                            @Nepster Yeah I was wondering about that, too. It would be great if someone explained about the volatile.

                            – RestInPeace
                            May 2 '15 at 5:27





                            @Nepster Yeah I was wondering about that, too. It would be great if someone explained about the volatile.

                            – RestInPeace
                            May 2 '15 at 5:27













                            257














                            Edit: Google engineers do not recommend this approach, as described by Dianne Hackborn (a.k.a. hackbod) in this StackOverflow post. Check out this blog post for more information.





                            You have to add this to the activity declaration in the manifest:



                            android:configChanges="orientation|screenSize"


                            so it looks like



                            <activity android:label="@string/app_name" 
                            android:configChanges="orientation|screenSize|keyboardHidden"
                            android:name=".your.package">


                            The matter is that the system destroys the activity when a change in the configuration occurs. See ConfigurationChanges.



                            So putting that in the configuration file avoids the system to destroy your activity. Instead it invokes the onConfigurationChanged(Configuration) method.






                            share|improve this answer





















                            • 21





                              This is definitely the best solution; as it simply rotates the layout (the behavior you expect in first place). Just be sure to put android:configChanges="orientation|keyboardHidden" (because of phones that have landscape keyboard)

                              – kape123
                              Oct 13 '10 at 20:41






                            • 24





                              This seems to be the behaviour I expect. However, the documentation indicates that the activity is destroyed "because any application resource, including layout files, can change based on any configuration value. Thus the only safe way to handle a configuration change is to re-retrieve all resources". And besides orientation, there are many more reasons for the configuration to change: keyboardHidden (I have edited the wiki answer already), uiMode (For example, going in or out of car mode ; night mode changing), etc. I now wonder wether this is actually a good answer.

                              – rds
                              Mar 10 '11 at 16:49








                            • 113





                              This is not an acceptable solution. It just masks the true issue.

                              – rf43
                              Oct 13 '11 at 0:55






                            • 18





                              Works, but not recommended by Google.

                              – Ed Burnette
                              Nov 9 '11 at 21:55






                            • 21





                              Please do not follow this approach here. DDosAttack is completely right. Imagine you are creating a progress dialog for a download or something else that takes a long time. As a user you won't stay on that activity and stare at it. You would switch to the home screen or to another app like a game or a phone call might come in or something else resource hungry that will eventually destroy your activity. And what then? You are facing the same old issue which is NOT solved with that neat little trick. The activity will be recreated all over again when the user comes back.

                              – tiguchi
                              Oct 1 '12 at 15:22
















                            257














                            Edit: Google engineers do not recommend this approach, as described by Dianne Hackborn (a.k.a. hackbod) in this StackOverflow post. Check out this blog post for more information.





                            You have to add this to the activity declaration in the manifest:



                            android:configChanges="orientation|screenSize"


                            so it looks like



                            <activity android:label="@string/app_name" 
                            android:configChanges="orientation|screenSize|keyboardHidden"
                            android:name=".your.package">


                            The matter is that the system destroys the activity when a change in the configuration occurs. See ConfigurationChanges.



                            So putting that in the configuration file avoids the system to destroy your activity. Instead it invokes the onConfigurationChanged(Configuration) method.






                            share|improve this answer





















                            • 21





                              This is definitely the best solution; as it simply rotates the layout (the behavior you expect in first place). Just be sure to put android:configChanges="orientation|keyboardHidden" (because of phones that have landscape keyboard)

                              – kape123
                              Oct 13 '10 at 20:41






                            • 24





                              This seems to be the behaviour I expect. However, the documentation indicates that the activity is destroyed "because any application resource, including layout files, can change based on any configuration value. Thus the only safe way to handle a configuration change is to re-retrieve all resources". And besides orientation, there are many more reasons for the configuration to change: keyboardHidden (I have edited the wiki answer already), uiMode (For example, going in or out of car mode ; night mode changing), etc. I now wonder wether this is actually a good answer.

                              – rds
                              Mar 10 '11 at 16:49








                            • 113





                              This is not an acceptable solution. It just masks the true issue.

                              – rf43
                              Oct 13 '11 at 0:55






                            • 18





                              Works, but not recommended by Google.

                              – Ed Burnette
                              Nov 9 '11 at 21:55






                            • 21





                              Please do not follow this approach here. DDosAttack is completely right. Imagine you are creating a progress dialog for a download or something else that takes a long time. As a user you won't stay on that activity and stare at it. You would switch to the home screen or to another app like a game or a phone call might come in or something else resource hungry that will eventually destroy your activity. And what then? You are facing the same old issue which is NOT solved with that neat little trick. The activity will be recreated all over again when the user comes back.

                              – tiguchi
                              Oct 1 '12 at 15:22














                            257












                            257








                            257







                            Edit: Google engineers do not recommend this approach, as described by Dianne Hackborn (a.k.a. hackbod) in this StackOverflow post. Check out this blog post for more information.





                            You have to add this to the activity declaration in the manifest:



                            android:configChanges="orientation|screenSize"


                            so it looks like



                            <activity android:label="@string/app_name" 
                            android:configChanges="orientation|screenSize|keyboardHidden"
                            android:name=".your.package">


                            The matter is that the system destroys the activity when a change in the configuration occurs. See ConfigurationChanges.



                            So putting that in the configuration file avoids the system to destroy your activity. Instead it invokes the onConfigurationChanged(Configuration) method.






                            share|improve this answer















                            Edit: Google engineers do not recommend this approach, as described by Dianne Hackborn (a.k.a. hackbod) in this StackOverflow post. Check out this blog post for more information.





                            You have to add this to the activity declaration in the manifest:



                            android:configChanges="orientation|screenSize"


                            so it looks like



                            <activity android:label="@string/app_name" 
                            android:configChanges="orientation|screenSize|keyboardHidden"
                            android:name=".your.package">


                            The matter is that the system destroys the activity when a change in the configuration occurs. See ConfigurationChanges.



                            So putting that in the configuration file avoids the system to destroy your activity. Instead it invokes the onConfigurationChanged(Configuration) method.







                            share|improve this answer














                            share|improve this answer



                            share|improve this answer








                            edited May 23 '17 at 12:10









                            Community

                            11




                            11










                            answered Mar 10 '10 at 16:50









                            sonxurxosonxurxo

                            2,8192102




                            2,8192102








                            • 21





                              This is definitely the best solution; as it simply rotates the layout (the behavior you expect in first place). Just be sure to put android:configChanges="orientation|keyboardHidden" (because of phones that have landscape keyboard)

                              – kape123
                              Oct 13 '10 at 20:41






                            • 24





                              This seems to be the behaviour I expect. However, the documentation indicates that the activity is destroyed "because any application resource, including layout files, can change based on any configuration value. Thus the only safe way to handle a configuration change is to re-retrieve all resources". And besides orientation, there are many more reasons for the configuration to change: keyboardHidden (I have edited the wiki answer already), uiMode (For example, going in or out of car mode ; night mode changing), etc. I now wonder wether this is actually a good answer.

                              – rds
                              Mar 10 '11 at 16:49








                            • 113





                              This is not an acceptable solution. It just masks the true issue.

                              – rf43
                              Oct 13 '11 at 0:55






                            • 18





                              Works, but not recommended by Google.

                              – Ed Burnette
                              Nov 9 '11 at 21:55






                            • 21





                              Please do not follow this approach here. DDosAttack is completely right. Imagine you are creating a progress dialog for a download or something else that takes a long time. As a user you won't stay on that activity and stare at it. You would switch to the home screen or to another app like a game or a phone call might come in or something else resource hungry that will eventually destroy your activity. And what then? You are facing the same old issue which is NOT solved with that neat little trick. The activity will be recreated all over again when the user comes back.

                              – tiguchi
                              Oct 1 '12 at 15:22














                            • 21





                              This is definitely the best solution; as it simply rotates the layout (the behavior you expect in first place). Just be sure to put android:configChanges="orientation|keyboardHidden" (because of phones that have landscape keyboard)

                              – kape123
                              Oct 13 '10 at 20:41






                            • 24





                              This seems to be the behaviour I expect. However, the documentation indicates that the activity is destroyed "because any application resource, including layout files, can change based on any configuration value. Thus the only safe way to handle a configuration change is to re-retrieve all resources". And besides orientation, there are many more reasons for the configuration to change: keyboardHidden (I have edited the wiki answer already), uiMode (For example, going in or out of car mode ; night mode changing), etc. I now wonder wether this is actually a good answer.

                              – rds
                              Mar 10 '11 at 16:49








                            • 113





                              This is not an acceptable solution. It just masks the true issue.

                              – rf43
                              Oct 13 '11 at 0:55






                            • 18





                              Works, but not recommended by Google.

                              – Ed Burnette
                              Nov 9 '11 at 21:55






                            • 21





                              Please do not follow this approach here. DDosAttack is completely right. Imagine you are creating a progress dialog for a download or something else that takes a long time. As a user you won't stay on that activity and stare at it. You would switch to the home screen or to another app like a game or a phone call might come in or something else resource hungry that will eventually destroy your activity. And what then? You are facing the same old issue which is NOT solved with that neat little trick. The activity will be recreated all over again when the user comes back.

                              – tiguchi
                              Oct 1 '12 at 15:22








                            21




                            21





                            This is definitely the best solution; as it simply rotates the layout (the behavior you expect in first place). Just be sure to put android:configChanges="orientation|keyboardHidden" (because of phones that have landscape keyboard)

                            – kape123
                            Oct 13 '10 at 20:41





                            This is definitely the best solution; as it simply rotates the layout (the behavior you expect in first place). Just be sure to put android:configChanges="orientation|keyboardHidden" (because of phones that have landscape keyboard)

                            – kape123
                            Oct 13 '10 at 20:41




                            24




                            24





                            This seems to be the behaviour I expect. However, the documentation indicates that the activity is destroyed "because any application resource, including layout files, can change based on any configuration value. Thus the only safe way to handle a configuration change is to re-retrieve all resources". And besides orientation, there are many more reasons for the configuration to change: keyboardHidden (I have edited the wiki answer already), uiMode (For example, going in or out of car mode ; night mode changing), etc. I now wonder wether this is actually a good answer.

                            – rds
                            Mar 10 '11 at 16:49







                            This seems to be the behaviour I expect. However, the documentation indicates that the activity is destroyed "because any application resource, including layout files, can change based on any configuration value. Thus the only safe way to handle a configuration change is to re-retrieve all resources". And besides orientation, there are many more reasons for the configuration to change: keyboardHidden (I have edited the wiki answer already), uiMode (For example, going in or out of car mode ; night mode changing), etc. I now wonder wether this is actually a good answer.

                            – rds
                            Mar 10 '11 at 16:49






                            113




                            113





                            This is not an acceptable solution. It just masks the true issue.

                            – rf43
                            Oct 13 '11 at 0:55





                            This is not an acceptable solution. It just masks the true issue.

                            – rf43
                            Oct 13 '11 at 0:55




                            18




                            18





                            Works, but not recommended by Google.

                            – Ed Burnette
                            Nov 9 '11 at 21:55





                            Works, but not recommended by Google.

                            – Ed Burnette
                            Nov 9 '11 at 21:55




                            21




                            21





                            Please do not follow this approach here. DDosAttack is completely right. Imagine you are creating a progress dialog for a download or something else that takes a long time. As a user you won't stay on that activity and stare at it. You would switch to the home screen or to another app like a game or a phone call might come in or something else resource hungry that will eventually destroy your activity. And what then? You are facing the same old issue which is NOT solved with that neat little trick. The activity will be recreated all over again when the user comes back.

                            – tiguchi
                            Oct 1 '12 at 15:22





                            Please do not follow this approach here. DDosAttack is completely right. Imagine you are creating a progress dialog for a download or something else that takes a long time. As a user you won't stay on that activity and stare at it. You would switch to the home screen or to another app like a game or a phone call might come in or something else resource hungry that will eventually destroy your activity. And what then? You are facing the same old issue which is NOT solved with that neat little trick. The activity will be recreated all over again when the user comes back.

                            – tiguchi
                            Oct 1 '12 at 15:22











                            66














                            I came up with a rock-solid solution for these issues that conforms with the 'Android Way' of things. I have all my long-running operations using the IntentService pattern.



                            That is, my activities broadcast intents, the IntentService does the work, saves the data in the DB and then broadcasts sticky intents. The sticky part is important, such that even if the Activity was paused during during the time after the user initiated the work and misses the real time broadcast from the IntentService we can still respond and pick up the data from the calling Activity. ProgressDialogs can work with this pattern quite nicely with onSaveInstanceState().



                            Basically, you need to save a flag that you have a progress dialog running in the saved instance bundle. Do not save the progress dialog object because this will leak the entire Activity. To have a persistent handle to the progress dialog, I store it as a weak reference in the application object. On orientation change or anything else that causes the Activity to pause (phone call, user hits home etc.) and then resume, I dismiss the old dialog and recreate a new dialog in the newly created Activity.



                            For indefinite progress dialogs this is easy. For progress bar style, you have to put the last known progress in the bundle and whatever information you're using locally in the activity to keep track of the progress. On restoring the progress, you'll use this information to re-spawn the progress bar in the same state as before and then update based on the current state of things.



                            So to summarize, putting long-running tasks into an IntentService coupled with judicious use of onSaveInstanceState() allows you to efficiently keep track of dialogs and restore then across the Activity life-cycle events. Relevant bits of Activity code are below. You'll also need logic in your BroadcastReceiver to handle Sticky intents appropriately, but that is beyond the scope of this.



                            public void doSignIn(View view) {
                            waiting=true;
                            AppClass app=(AppClass) getApplication();
                            String logingon=getString(R.string.signon);
                            app.Dialog=new WeakReference<ProgressDialog>(ProgressDialog.show(AddAccount.this, "", logingon, true));
                            ...
                            }

                            @Override
                            protected void onSaveInstanceState(Bundle saveState) {
                            super.onSaveInstanceState(saveState);
                            saveState.putBoolean("waiting",waiting);
                            }

                            @Override
                            public void onCreate(Bundle savedInstanceState) {
                            super.onCreate(savedInstanceState);
                            if(savedInstanceState!=null) {
                            restoreProgress(savedInstanceState);
                            }
                            ...
                            }

                            private void restoreProgress(Bundle savedInstanceState) {
                            waiting=savedInstanceState.getBoolean("waiting");
                            if (waiting) {
                            AppClass app=(AppClass) getApplication();
                            ProgressDialog refresher=(ProgressDialog) app.Dialog.get();
                            refresher.dismiss();
                            String logingon=getString(R.string.signon);
                            app.Dialog=new WeakReference<ProgressDialog>(ProgressDialog.show(AddAccount.this, "", logingon, true));
                            }
                            }





                            share|improve this answer


























                            • seems a nice solution

                              – Derekyy
                              Oct 14 '15 at 9:02











                            • "I have all my long-running operations using the IntentService pattern." This is not a perfect solution because it is like to shoot out of cannon into sparrows and a lot boilerplate code, for more you can watch youtube.com/watch?v=NJsq0TU0qeg

                              – user3871754
                              Jun 17 '16 at 11:04


















                            66














                            I came up with a rock-solid solution for these issues that conforms with the 'Android Way' of things. I have all my long-running operations using the IntentService pattern.



                            That is, my activities broadcast intents, the IntentService does the work, saves the data in the DB and then broadcasts sticky intents. The sticky part is important, such that even if the Activity was paused during during the time after the user initiated the work and misses the real time broadcast from the IntentService we can still respond and pick up the data from the calling Activity. ProgressDialogs can work with this pattern quite nicely with onSaveInstanceState().



                            Basically, you need to save a flag that you have a progress dialog running in the saved instance bundle. Do not save the progress dialog object because this will leak the entire Activity. To have a persistent handle to the progress dialog, I store it as a weak reference in the application object. On orientation change or anything else that causes the Activity to pause (phone call, user hits home etc.) and then resume, I dismiss the old dialog and recreate a new dialog in the newly created Activity.



                            For indefinite progress dialogs this is easy. For progress bar style, you have to put the last known progress in the bundle and whatever information you're using locally in the activity to keep track of the progress. On restoring the progress, you'll use this information to re-spawn the progress bar in the same state as before and then update based on the current state of things.



                            So to summarize, putting long-running tasks into an IntentService coupled with judicious use of onSaveInstanceState() allows you to efficiently keep track of dialogs and restore then across the Activity life-cycle events. Relevant bits of Activity code are below. You'll also need logic in your BroadcastReceiver to handle Sticky intents appropriately, but that is beyond the scope of this.



                            public void doSignIn(View view) {
                            waiting=true;
                            AppClass app=(AppClass) getApplication();
                            String logingon=getString(R.string.signon);
                            app.Dialog=new WeakReference<ProgressDialog>(ProgressDialog.show(AddAccount.this, "", logingon, true));
                            ...
                            }

                            @Override
                            protected void onSaveInstanceState(Bundle saveState) {
                            super.onSaveInstanceState(saveState);
                            saveState.putBoolean("waiting",waiting);
                            }

                            @Override
                            public void onCreate(Bundle savedInstanceState) {
                            super.onCreate(savedInstanceState);
                            if(savedInstanceState!=null) {
                            restoreProgress(savedInstanceState);
                            }
                            ...
                            }

                            private void restoreProgress(Bundle savedInstanceState) {
                            waiting=savedInstanceState.getBoolean("waiting");
                            if (waiting) {
                            AppClass app=(AppClass) getApplication();
                            ProgressDialog refresher=(ProgressDialog) app.Dialog.get();
                            refresher.dismiss();
                            String logingon=getString(R.string.signon);
                            app.Dialog=new WeakReference<ProgressDialog>(ProgressDialog.show(AddAccount.this, "", logingon, true));
                            }
                            }





                            share|improve this answer


























                            • seems a nice solution

                              – Derekyy
                              Oct 14 '15 at 9:02











                            • "I have all my long-running operations using the IntentService pattern." This is not a perfect solution because it is like to shoot out of cannon into sparrows and a lot boilerplate code, for more you can watch youtube.com/watch?v=NJsq0TU0qeg

                              – user3871754
                              Jun 17 '16 at 11:04
















                            66












                            66








                            66







                            I came up with a rock-solid solution for these issues that conforms with the 'Android Way' of things. I have all my long-running operations using the IntentService pattern.



                            That is, my activities broadcast intents, the IntentService does the work, saves the data in the DB and then broadcasts sticky intents. The sticky part is important, such that even if the Activity was paused during during the time after the user initiated the work and misses the real time broadcast from the IntentService we can still respond and pick up the data from the calling Activity. ProgressDialogs can work with this pattern quite nicely with onSaveInstanceState().



                            Basically, you need to save a flag that you have a progress dialog running in the saved instance bundle. Do not save the progress dialog object because this will leak the entire Activity. To have a persistent handle to the progress dialog, I store it as a weak reference in the application object. On orientation change or anything else that causes the Activity to pause (phone call, user hits home etc.) and then resume, I dismiss the old dialog and recreate a new dialog in the newly created Activity.



                            For indefinite progress dialogs this is easy. For progress bar style, you have to put the last known progress in the bundle and whatever information you're using locally in the activity to keep track of the progress. On restoring the progress, you'll use this information to re-spawn the progress bar in the same state as before and then update based on the current state of things.



                            So to summarize, putting long-running tasks into an IntentService coupled with judicious use of onSaveInstanceState() allows you to efficiently keep track of dialogs and restore then across the Activity life-cycle events. Relevant bits of Activity code are below. You'll also need logic in your BroadcastReceiver to handle Sticky intents appropriately, but that is beyond the scope of this.



                            public void doSignIn(View view) {
                            waiting=true;
                            AppClass app=(AppClass) getApplication();
                            String logingon=getString(R.string.signon);
                            app.Dialog=new WeakReference<ProgressDialog>(ProgressDialog.show(AddAccount.this, "", logingon, true));
                            ...
                            }

                            @Override
                            protected void onSaveInstanceState(Bundle saveState) {
                            super.onSaveInstanceState(saveState);
                            saveState.putBoolean("waiting",waiting);
                            }

                            @Override
                            public void onCreate(Bundle savedInstanceState) {
                            super.onCreate(savedInstanceState);
                            if(savedInstanceState!=null) {
                            restoreProgress(savedInstanceState);
                            }
                            ...
                            }

                            private void restoreProgress(Bundle savedInstanceState) {
                            waiting=savedInstanceState.getBoolean("waiting");
                            if (waiting) {
                            AppClass app=(AppClass) getApplication();
                            ProgressDialog refresher=(ProgressDialog) app.Dialog.get();
                            refresher.dismiss();
                            String logingon=getString(R.string.signon);
                            app.Dialog=new WeakReference<ProgressDialog>(ProgressDialog.show(AddAccount.this, "", logingon, true));
                            }
                            }





                            share|improve this answer















                            I came up with a rock-solid solution for these issues that conforms with the 'Android Way' of things. I have all my long-running operations using the IntentService pattern.



                            That is, my activities broadcast intents, the IntentService does the work, saves the data in the DB and then broadcasts sticky intents. The sticky part is important, such that even if the Activity was paused during during the time after the user initiated the work and misses the real time broadcast from the IntentService we can still respond and pick up the data from the calling Activity. ProgressDialogs can work with this pattern quite nicely with onSaveInstanceState().



                            Basically, you need to save a flag that you have a progress dialog running in the saved instance bundle. Do not save the progress dialog object because this will leak the entire Activity. To have a persistent handle to the progress dialog, I store it as a weak reference in the application object. On orientation change or anything else that causes the Activity to pause (phone call, user hits home etc.) and then resume, I dismiss the old dialog and recreate a new dialog in the newly created Activity.



                            For indefinite progress dialogs this is easy. For progress bar style, you have to put the last known progress in the bundle and whatever information you're using locally in the activity to keep track of the progress. On restoring the progress, you'll use this information to re-spawn the progress bar in the same state as before and then update based on the current state of things.



                            So to summarize, putting long-running tasks into an IntentService coupled with judicious use of onSaveInstanceState() allows you to efficiently keep track of dialogs and restore then across the Activity life-cycle events. Relevant bits of Activity code are below. You'll also need logic in your BroadcastReceiver to handle Sticky intents appropriately, but that is beyond the scope of this.



                            public void doSignIn(View view) {
                            waiting=true;
                            AppClass app=(AppClass) getApplication();
                            String logingon=getString(R.string.signon);
                            app.Dialog=new WeakReference<ProgressDialog>(ProgressDialog.show(AddAccount.this, "", logingon, true));
                            ...
                            }

                            @Override
                            protected void onSaveInstanceState(Bundle saveState) {
                            super.onSaveInstanceState(saveState);
                            saveState.putBoolean("waiting",waiting);
                            }

                            @Override
                            public void onCreate(Bundle savedInstanceState) {
                            super.onCreate(savedInstanceState);
                            if(savedInstanceState!=null) {
                            restoreProgress(savedInstanceState);
                            }
                            ...
                            }

                            private void restoreProgress(Bundle savedInstanceState) {
                            waiting=savedInstanceState.getBoolean("waiting");
                            if (waiting) {
                            AppClass app=(AppClass) getApplication();
                            ProgressDialog refresher=(ProgressDialog) app.Dialog.get();
                            refresher.dismiss();
                            String logingon=getString(R.string.signon);
                            app.Dialog=new WeakReference<ProgressDialog>(ProgressDialog.show(AddAccount.this, "", logingon, true));
                            }
                            }






                            share|improve this answer














                            share|improve this answer



                            share|improve this answer








                            edited Nov 19 '18 at 10:54









                            neonblitzer

                            3817




                            3817










                            answered Dec 19 '10 at 2:21









                            jfelectronjfelectron

                            96886




                            96886













                            • seems a nice solution

                              – Derekyy
                              Oct 14 '15 at 9:02











                            • "I have all my long-running operations using the IntentService pattern." This is not a perfect solution because it is like to shoot out of cannon into sparrows and a lot boilerplate code, for more you can watch youtube.com/watch?v=NJsq0TU0qeg

                              – user3871754
                              Jun 17 '16 at 11:04





















                            • seems a nice solution

                              – Derekyy
                              Oct 14 '15 at 9:02











                            • "I have all my long-running operations using the IntentService pattern." This is not a perfect solution because it is like to shoot out of cannon into sparrows and a lot boilerplate code, for more you can watch youtube.com/watch?v=NJsq0TU0qeg

                              – user3871754
                              Jun 17 '16 at 11:04



















                            seems a nice solution

                            – Derekyy
                            Oct 14 '15 at 9:02





                            seems a nice solution

                            – Derekyy
                            Oct 14 '15 at 9:02













                            "I have all my long-running operations using the IntentService pattern." This is not a perfect solution because it is like to shoot out of cannon into sparrows and a lot boilerplate code, for more you can watch youtube.com/watch?v=NJsq0TU0qeg

                            – user3871754
                            Jun 17 '16 at 11:04







                            "I have all my long-running operations using the IntentService pattern." This is not a perfect solution because it is like to shoot out of cannon into sparrows and a lot boilerplate code, for more you can watch youtube.com/watch?v=NJsq0TU0qeg

                            – user3871754
                            Jun 17 '16 at 11:04













                            26














                            I met the same problem. My activity needs to parse some data from a URL and it's slow. So I create a thread to do so, then show a progress dialog. I let the thread post a message back to UI thread via Handler when it's finished. In Handler.handleMessage, I get the data object (ready now) from thread and populate it to UI. So it's very similar to your example.



                            After a lot of trial and error it looks like I found a solution. At least now I can rotate screen at any moment, before or after the thread is done. In all tests, the dialog is properly closed and all behaviors are as expected.



                            What I did is shown below. The goal is to fill my data model (mDataObject) and then populate it to UI. Should allow screen rotation at any moment without surprise.



                            class MyActivity {

                            private MyDataObject mDataObject = null;
                            private static MyThread mParserThread = null; // static, or make it singleton

                            OnCreate() {
                            ...
                            Object retained = this.getLastNonConfigurationInstance();
                            if(retained != null) {
                            // data is already completely obtained before config change
                            // by my previous self.
                            // no need to create thread or show dialog at all
                            mDataObject = (MyDataObject) retained;
                            populateUI();
                            } else if(mParserThread != null && mParserThread.isAlive()){
                            // note: mParserThread is a static member or singleton object.
                            // config changed during parsing in previous instance. swap handler
                            // then wait for it to finish.
                            mParserThread.setHandler(new MyHandler());
                            } else {
                            // no data and no thread. likely initial run
                            // create thread, show dialog
                            mParserThread = new MyThread(..., new MyHandler());
                            mParserThread.start();
                            showDialog(DIALOG_PROGRESS);
                            }
                            }

                            // http://android-developers.blogspot.com/2009/02/faster-screen-orientation-change.html
                            public Object onRetainNonConfigurationInstance() {
                            // my future self can get this without re-downloading
                            // if it's already ready.
                            return mDataObject;
                            }

                            // use Activity.showDialog instead of ProgressDialog.show
                            // so the dialog can be automatically managed across config change
                            @Override
                            protected Dialog onCreateDialog(int id) {
                            // show progress dialog here
                            }

                            // inner class of MyActivity
                            private class MyHandler extends Handler {
                            public void handleMessage(msg) {
                            mDataObject = mParserThread.getDataObject();
                            populateUI();
                            dismissDialog(DIALOG_PROGRESS);
                            }
                            }
                            }

                            class MyThread extends Thread {
                            Handler mHandler;
                            MyDataObject mDataObject;

                            // constructor with handler param
                            public MyHandler(..., Handler h) {
                            ...
                            mHandler = h;
                            }

                            public void setHandler(Handler h) { mHandler = h; } // for handler swapping after config change
                            public MyDataObject getDataObject() { return mDataObject; } // return data object (completed) to caller

                            public void run() {
                            mDataObject = new MyDataObject();
                            // do the lengthy task to fill mDataObject with data
                            lengthyTask(mDataObject);
                            // done. notify activity
                            mHandler.sendEmptyMessage(0); // tell activity: i'm ready. come pick up the data.
                            }
                            }


                            That's what works for me. I don't know if this is the "correct" method as designed by Android -- they claim this "destroy/recreate activity during screen rotation" actually makes things easier, so I guess it shouldn't be too tricky.



                            Let me know if you see a problem in my code. As said above I don't really know if there is any side effect.






                            share|improve this answer





















                            • 1





                              Thanks a lot! The hint to onRetainNonConfigurationInstance() and getLastNonConfigurationInstance() helped me to solve my problem. Thumbs up!

                              – sven
                              Oct 28 '10 at 13:42
















                            26














                            I met the same problem. My activity needs to parse some data from a URL and it's slow. So I create a thread to do so, then show a progress dialog. I let the thread post a message back to UI thread via Handler when it's finished. In Handler.handleMessage, I get the data object (ready now) from thread and populate it to UI. So it's very similar to your example.



                            After a lot of trial and error it looks like I found a solution. At least now I can rotate screen at any moment, before or after the thread is done. In all tests, the dialog is properly closed and all behaviors are as expected.



                            What I did is shown below. The goal is to fill my data model (mDataObject) and then populate it to UI. Should allow screen rotation at any moment without surprise.



                            class MyActivity {

                            private MyDataObject mDataObject = null;
                            private static MyThread mParserThread = null; // static, or make it singleton

                            OnCreate() {
                            ...
                            Object retained = this.getLastNonConfigurationInstance();
                            if(retained != null) {
                            // data is already completely obtained before config change
                            // by my previous self.
                            // no need to create thread or show dialog at all
                            mDataObject = (MyDataObject) retained;
                            populateUI();
                            } else if(mParserThread != null && mParserThread.isAlive()){
                            // note: mParserThread is a static member or singleton object.
                            // config changed during parsing in previous instance. swap handler
                            // then wait for it to finish.
                            mParserThread.setHandler(new MyHandler());
                            } else {
                            // no data and no thread. likely initial run
                            // create thread, show dialog
                            mParserThread = new MyThread(..., new MyHandler());
                            mParserThread.start();
                            showDialog(DIALOG_PROGRESS);
                            }
                            }

                            // http://android-developers.blogspot.com/2009/02/faster-screen-orientation-change.html
                            public Object onRetainNonConfigurationInstance() {
                            // my future self can get this without re-downloading
                            // if it's already ready.
                            return mDataObject;
                            }

                            // use Activity.showDialog instead of ProgressDialog.show
                            // so the dialog can be automatically managed across config change
                            @Override
                            protected Dialog onCreateDialog(int id) {
                            // show progress dialog here
                            }

                            // inner class of MyActivity
                            private class MyHandler extends Handler {
                            public void handleMessage(msg) {
                            mDataObject = mParserThread.getDataObject();
                            populateUI();
                            dismissDialog(DIALOG_PROGRESS);
                            }
                            }
                            }

                            class MyThread extends Thread {
                            Handler mHandler;
                            MyDataObject mDataObject;

                            // constructor with handler param
                            public MyHandler(..., Handler h) {
                            ...
                            mHandler = h;
                            }

                            public void setHandler(Handler h) { mHandler = h; } // for handler swapping after config change
                            public MyDataObject getDataObject() { return mDataObject; } // return data object (completed) to caller

                            public void run() {
                            mDataObject = new MyDataObject();
                            // do the lengthy task to fill mDataObject with data
                            lengthyTask(mDataObject);
                            // done. notify activity
                            mHandler.sendEmptyMessage(0); // tell activity: i'm ready. come pick up the data.
                            }
                            }


                            That's what works for me. I don't know if this is the "correct" method as designed by Android -- they claim this "destroy/recreate activity during screen rotation" actually makes things easier, so I guess it shouldn't be too tricky.



                            Let me know if you see a problem in my code. As said above I don't really know if there is any side effect.






                            share|improve this answer





















                            • 1





                              Thanks a lot! The hint to onRetainNonConfigurationInstance() and getLastNonConfigurationInstance() helped me to solve my problem. Thumbs up!

                              – sven
                              Oct 28 '10 at 13:42














                            26












                            26








                            26







                            I met the same problem. My activity needs to parse some data from a URL and it's slow. So I create a thread to do so, then show a progress dialog. I let the thread post a message back to UI thread via Handler when it's finished. In Handler.handleMessage, I get the data object (ready now) from thread and populate it to UI. So it's very similar to your example.



                            After a lot of trial and error it looks like I found a solution. At least now I can rotate screen at any moment, before or after the thread is done. In all tests, the dialog is properly closed and all behaviors are as expected.



                            What I did is shown below. The goal is to fill my data model (mDataObject) and then populate it to UI. Should allow screen rotation at any moment without surprise.



                            class MyActivity {

                            private MyDataObject mDataObject = null;
                            private static MyThread mParserThread = null; // static, or make it singleton

                            OnCreate() {
                            ...
                            Object retained = this.getLastNonConfigurationInstance();
                            if(retained != null) {
                            // data is already completely obtained before config change
                            // by my previous self.
                            // no need to create thread or show dialog at all
                            mDataObject = (MyDataObject) retained;
                            populateUI();
                            } else if(mParserThread != null && mParserThread.isAlive()){
                            // note: mParserThread is a static member or singleton object.
                            // config changed during parsing in previous instance. swap handler
                            // then wait for it to finish.
                            mParserThread.setHandler(new MyHandler());
                            } else {
                            // no data and no thread. likely initial run
                            // create thread, show dialog
                            mParserThread = new MyThread(..., new MyHandler());
                            mParserThread.start();
                            showDialog(DIALOG_PROGRESS);
                            }
                            }

                            // http://android-developers.blogspot.com/2009/02/faster-screen-orientation-change.html
                            public Object onRetainNonConfigurationInstance() {
                            // my future self can get this without re-downloading
                            // if it's already ready.
                            return mDataObject;
                            }

                            // use Activity.showDialog instead of ProgressDialog.show
                            // so the dialog can be automatically managed across config change
                            @Override
                            protected Dialog onCreateDialog(int id) {
                            // show progress dialog here
                            }

                            // inner class of MyActivity
                            private class MyHandler extends Handler {
                            public void handleMessage(msg) {
                            mDataObject = mParserThread.getDataObject();
                            populateUI();
                            dismissDialog(DIALOG_PROGRESS);
                            }
                            }
                            }

                            class MyThread extends Thread {
                            Handler mHandler;
                            MyDataObject mDataObject;

                            // constructor with handler param
                            public MyHandler(..., Handler h) {
                            ...
                            mHandler = h;
                            }

                            public void setHandler(Handler h) { mHandler = h; } // for handler swapping after config change
                            public MyDataObject getDataObject() { return mDataObject; } // return data object (completed) to caller

                            public void run() {
                            mDataObject = new MyDataObject();
                            // do the lengthy task to fill mDataObject with data
                            lengthyTask(mDataObject);
                            // done. notify activity
                            mHandler.sendEmptyMessage(0); // tell activity: i'm ready. come pick up the data.
                            }
                            }


                            That's what works for me. I don't know if this is the "correct" method as designed by Android -- they claim this "destroy/recreate activity during screen rotation" actually makes things easier, so I guess it shouldn't be too tricky.



                            Let me know if you see a problem in my code. As said above I don't really know if there is any side effect.






                            share|improve this answer















                            I met the same problem. My activity needs to parse some data from a URL and it's slow. So I create a thread to do so, then show a progress dialog. I let the thread post a message back to UI thread via Handler when it's finished. In Handler.handleMessage, I get the data object (ready now) from thread and populate it to UI. So it's very similar to your example.



                            After a lot of trial and error it looks like I found a solution. At least now I can rotate screen at any moment, before or after the thread is done. In all tests, the dialog is properly closed and all behaviors are as expected.



                            What I did is shown below. The goal is to fill my data model (mDataObject) and then populate it to UI. Should allow screen rotation at any moment without surprise.



                            class MyActivity {

                            private MyDataObject mDataObject = null;
                            private static MyThread mParserThread = null; // static, or make it singleton

                            OnCreate() {
                            ...
                            Object retained = this.getLastNonConfigurationInstance();
                            if(retained != null) {
                            // data is already completely obtained before config change
                            // by my previous self.
                            // no need to create thread or show dialog at all
                            mDataObject = (MyDataObject) retained;
                            populateUI();
                            } else if(mParserThread != null && mParserThread.isAlive()){
                            // note: mParserThread is a static member or singleton object.
                            // config changed during parsing in previous instance. swap handler
                            // then wait for it to finish.
                            mParserThread.setHandler(new MyHandler());
                            } else {
                            // no data and no thread. likely initial run
                            // create thread, show dialog
                            mParserThread = new MyThread(..., new MyHandler());
                            mParserThread.start();
                            showDialog(DIALOG_PROGRESS);
                            }
                            }

                            // http://android-developers.blogspot.com/2009/02/faster-screen-orientation-change.html
                            public Object onRetainNonConfigurationInstance() {
                            // my future self can get this without re-downloading
                            // if it's already ready.
                            return mDataObject;
                            }

                            // use Activity.showDialog instead of ProgressDialog.show
                            // so the dialog can be automatically managed across config change
                            @Override
                            protected Dialog onCreateDialog(int id) {
                            // show progress dialog here
                            }

                            // inner class of MyActivity
                            private class MyHandler extends Handler {
                            public void handleMessage(msg) {
                            mDataObject = mParserThread.getDataObject();
                            populateUI();
                            dismissDialog(DIALOG_PROGRESS);
                            }
                            }
                            }

                            class MyThread extends Thread {
                            Handler mHandler;
                            MyDataObject mDataObject;

                            // constructor with handler param
                            public MyHandler(..., Handler h) {
                            ...
                            mHandler = h;
                            }

                            public void setHandler(Handler h) { mHandler = h; } // for handler swapping after config change
                            public MyDataObject getDataObject() { return mDataObject; } // return data object (completed) to caller

                            public void run() {
                            mDataObject = new MyDataObject();
                            // do the lengthy task to fill mDataObject with data
                            lengthyTask(mDataObject);
                            // done. notify activity
                            mHandler.sendEmptyMessage(0); // tell activity: i'm ready. come pick up the data.
                            }
                            }


                            That's what works for me. I don't know if this is the "correct" method as designed by Android -- they claim this "destroy/recreate activity during screen rotation" actually makes things easier, so I guess it shouldn't be too tricky.



                            Let me know if you see a problem in my code. As said above I don't really know if there is any side effect.







                            share|improve this answer














                            share|improve this answer



                            share|improve this answer








                            edited Nov 19 '18 at 11:46









                            neonblitzer

                            3817




                            3817










                            answered Feb 19 '10 at 8:42









                            samsonsusamsonsu

                            32645




                            32645








                            • 1





                              Thanks a lot! The hint to onRetainNonConfigurationInstance() and getLastNonConfigurationInstance() helped me to solve my problem. Thumbs up!

                              – sven
                              Oct 28 '10 at 13:42














                            • 1





                              Thanks a lot! The hint to onRetainNonConfigurationInstance() and getLastNonConfigurationInstance() helped me to solve my problem. Thumbs up!

                              – sven
                              Oct 28 '10 at 13:42








                            1




                            1





                            Thanks a lot! The hint to onRetainNonConfigurationInstance() and getLastNonConfigurationInstance() helped me to solve my problem. Thumbs up!

                            – sven
                            Oct 28 '10 at 13:42





                            Thanks a lot! The hint to onRetainNonConfigurationInstance() and getLastNonConfigurationInstance() helped me to solve my problem. Thumbs up!

                            – sven
                            Oct 28 '10 at 13:42











                            14














                            The original perceived problem was that the code would not survive a screen orientation change. Apparently this was "solved" by having the program handle the screen orientation change itself, instead of letting the UI framework do it (via calling onDestroy)).



                            I would submit that if the underlying problem is that the program will not survive onDestroy(), then the accepted solution is just a workaround that leaves the program with serious other problems and vulnerabilities. Remember that the Android framework specifically states that your activity is at risk for being destroyed almost at any time due to circumstances outside your control. Therefore, your activity must be able to survive onDestroy() and subsequent onCreate() for any reason, not just a screen orientation change.



                            If you are going to accept handling screen orientation changes yourself to solve the OP's problem, you need to verify that other causes of onDestroy() do not result in the same error. Are you able to do this? If not, I would question whether the "accepted" answer is really a very good one.






                            share|improve this answer




























                              14














                              The original perceived problem was that the code would not survive a screen orientation change. Apparently this was "solved" by having the program handle the screen orientation change itself, instead of letting the UI framework do it (via calling onDestroy)).



                              I would submit that if the underlying problem is that the program will not survive onDestroy(), then the accepted solution is just a workaround that leaves the program with serious other problems and vulnerabilities. Remember that the Android framework specifically states that your activity is at risk for being destroyed almost at any time due to circumstances outside your control. Therefore, your activity must be able to survive onDestroy() and subsequent onCreate() for any reason, not just a screen orientation change.



                              If you are going to accept handling screen orientation changes yourself to solve the OP's problem, you need to verify that other causes of onDestroy() do not result in the same error. Are you able to do this? If not, I would question whether the "accepted" answer is really a very good one.






                              share|improve this answer


























                                14












                                14








                                14







                                The original perceived problem was that the code would not survive a screen orientation change. Apparently this was "solved" by having the program handle the screen orientation change itself, instead of letting the UI framework do it (via calling onDestroy)).



                                I would submit that if the underlying problem is that the program will not survive onDestroy(), then the accepted solution is just a workaround that leaves the program with serious other problems and vulnerabilities. Remember that the Android framework specifically states that your activity is at risk for being destroyed almost at any time due to circumstances outside your control. Therefore, your activity must be able to survive onDestroy() and subsequent onCreate() for any reason, not just a screen orientation change.



                                If you are going to accept handling screen orientation changes yourself to solve the OP's problem, you need to verify that other causes of onDestroy() do not result in the same error. Are you able to do this? If not, I would question whether the "accepted" answer is really a very good one.






                                share|improve this answer













                                The original perceived problem was that the code would not survive a screen orientation change. Apparently this was "solved" by having the program handle the screen orientation change itself, instead of letting the UI framework do it (via calling onDestroy)).



                                I would submit that if the underlying problem is that the program will not survive onDestroy(), then the accepted solution is just a workaround that leaves the program with serious other problems and vulnerabilities. Remember that the Android framework specifically states that your activity is at risk for being destroyed almost at any time due to circumstances outside your control. Therefore, your activity must be able to survive onDestroy() and subsequent onCreate() for any reason, not just a screen orientation change.



                                If you are going to accept handling screen orientation changes yourself to solve the OP's problem, you need to verify that other causes of onDestroy() do not result in the same error. Are you able to do this? If not, I would question whether the "accepted" answer is really a very good one.







                                share|improve this answer












                                share|improve this answer



                                share|improve this answer










                                answered May 23 '11 at 21:21









                                gymshoegymshoe

                                3,47541516




                                3,47541516























                                    14














                                    My solution was to extend the ProgressDialog class to get my own MyProgressDialog.

                                    I redefined show() and dismiss() methods to lock the orientation before showing the Dialog and unlock it back when Dialog is dismissed. So when the Dialog is shown and the orientation of the device changes, the orientation of the screen remains until dismiss() is called, then screen-orientation changes according to sensor-values/device-orientation.



                                    Here is my code:



                                    public class MyProgressDialog extends ProgressDialog {
                                    private Context mContext;

                                    public MyProgressDialog(Context context) {
                                    super(context);
                                    mContext = context;
                                    }

                                    public MyProgressDialog(Context context, int theme) {
                                    super(context, theme);
                                    mContext = context;
                                    }

                                    public void show() {
                                    if (mContext.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT)
                                    ((Activity) mContext).setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
                                    else
                                    ((Activity) mContext).setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
                                    super.show();
                                    }

                                    public void dismiss() {
                                    super.dismiss();
                                    ((Activity) mContext).setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);
                                    }

                                    }





                                    share|improve this answer






























                                      14














                                      My solution was to extend the ProgressDialog class to get my own MyProgressDialog.

                                      I redefined show() and dismiss() methods to lock the orientation before showing the Dialog and unlock it back when Dialog is dismissed. So when the Dialog is shown and the orientation of the device changes, the orientation of the screen remains until dismiss() is called, then screen-orientation changes according to sensor-values/device-orientation.



                                      Here is my code:



                                      public class MyProgressDialog extends ProgressDialog {
                                      private Context mContext;

                                      public MyProgressDialog(Context context) {
                                      super(context);
                                      mContext = context;
                                      }

                                      public MyProgressDialog(Context context, int theme) {
                                      super(context, theme);
                                      mContext = context;
                                      }

                                      public void show() {
                                      if (mContext.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT)
                                      ((Activity) mContext).setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
                                      else
                                      ((Activity) mContext).setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
                                      super.show();
                                      }

                                      public void dismiss() {
                                      super.dismiss();
                                      ((Activity) mContext).setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);
                                      }

                                      }





                                      share|improve this answer




























                                        14












                                        14








                                        14







                                        My solution was to extend the ProgressDialog class to get my own MyProgressDialog.

                                        I redefined show() and dismiss() methods to lock the orientation before showing the Dialog and unlock it back when Dialog is dismissed. So when the Dialog is shown and the orientation of the device changes, the orientation of the screen remains until dismiss() is called, then screen-orientation changes according to sensor-values/device-orientation.



                                        Here is my code:



                                        public class MyProgressDialog extends ProgressDialog {
                                        private Context mContext;

                                        public MyProgressDialog(Context context) {
                                        super(context);
                                        mContext = context;
                                        }

                                        public MyProgressDialog(Context context, int theme) {
                                        super(context, theme);
                                        mContext = context;
                                        }

                                        public void show() {
                                        if (mContext.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT)
                                        ((Activity) mContext).setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
                                        else
                                        ((Activity) mContext).setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
                                        super.show();
                                        }

                                        public void dismiss() {
                                        super.dismiss();
                                        ((Activity) mContext).setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);
                                        }

                                        }





                                        share|improve this answer















                                        My solution was to extend the ProgressDialog class to get my own MyProgressDialog.

                                        I redefined show() and dismiss() methods to lock the orientation before showing the Dialog and unlock it back when Dialog is dismissed. So when the Dialog is shown and the orientation of the device changes, the orientation of the screen remains until dismiss() is called, then screen-orientation changes according to sensor-values/device-orientation.



                                        Here is my code:



                                        public class MyProgressDialog extends ProgressDialog {
                                        private Context mContext;

                                        public MyProgressDialog(Context context) {
                                        super(context);
                                        mContext = context;
                                        }

                                        public MyProgressDialog(Context context, int theme) {
                                        super(context, theme);
                                        mContext = context;
                                        }

                                        public void show() {
                                        if (mContext.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT)
                                        ((Activity) mContext).setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
                                        else
                                        ((Activity) mContext).setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
                                        super.show();
                                        }

                                        public void dismiss() {
                                        super.dismiss();
                                        ((Activity) mContext).setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);
                                        }

                                        }






                                        share|improve this answer














                                        share|improve this answer



                                        share|improve this answer








                                        edited Apr 20 '15 at 16:00









                                        Catalina

                                        898923




                                        898923










                                        answered Aug 22 '12 at 12:30









                                        OliOli

                                        393411




                                        393411























                                            8














                                            I faced this same problem, and I came up with a solution that didn't invole using the ProgressDialog and I get faster results.



                                            What I did was create a layout that has a ProgressBar in it.



                                            <?xml version="1.0" encoding="utf-8"?>
                                            <RelativeLayout
                                            xmlns:android="http://schemas.android.com/apk/res/android"
                                            android:layout_width="fill_parent"
                                            android:layout_height="fill_parent">
                                            <ProgressBar
                                            android:id="@+id/progressImage"
                                            android:layout_width="wrap_content"
                                            android:layout_height="wrap_content"
                                            android:layout_centerInParent="true"
                                            />
                                            </RelativeLayout>


                                            Then in the onCreate method do the following



                                            public void onCreate(Bundle icicle) {
                                            super.onCreate(icicle);
                                            setContentView(R.layout.progress);
                                            }


                                            Then do the long task in a thread, and when that's finished have a Runnable set the content view to the real layout you want to use for this activity.



                                            For example:



                                            mHandler.post(new Runnable(){

                                            public void run() {
                                            setContentView(R.layout.my_layout);
                                            }
                                            });


                                            This is what I did, and I've found that it runs faster than showing the ProgressDialog and it's less intrusive and has a better look in my opinion.



                                            However, if you're wanting to use the ProgressDialog, then this answer isn't for you.






                                            share|improve this answer
























                                            • This solution is elegant in a simple use case, but has drawbacks. You need to rebuild the full content view. setContentView(R.layout.my_layout); is not sufficient; you need to set all listeners, reset data, etc.

                                              – rds
                                              Mar 10 '11 at 23:40













                                            • @rds you are right. This is really only a solution to a simple case, or if you need to do some heavy lifting in your onCreate method before displaying your view.

                                              – Pzanno
                                              Mar 11 '11 at 19:12











                                            • I don't quite get it. Instead of settings listeners in the onCreate(), as we would typically do, we could set them up in the run(). Am I missing something here?

                                              – Code Poet
                                              Dec 11 '11 at 19:03
















                                            8














                                            I faced this same problem, and I came up with a solution that didn't invole using the ProgressDialog and I get faster results.



                                            What I did was create a layout that has a ProgressBar in it.



                                            <?xml version="1.0" encoding="utf-8"?>
                                            <RelativeLayout
                                            xmlns:android="http://schemas.android.com/apk/res/android"
                                            android:layout_width="fill_parent"
                                            android:layout_height="fill_parent">
                                            <ProgressBar
                                            android:id="@+id/progressImage"
                                            android:layout_width="wrap_content"
                                            android:layout_height="wrap_content"
                                            android:layout_centerInParent="true"
                                            />
                                            </RelativeLayout>


                                            Then in the onCreate method do the following



                                            public void onCreate(Bundle icicle) {
                                            super.onCreate(icicle);
                                            setContentView(R.layout.progress);
                                            }


                                            Then do the long task in a thread, and when that's finished have a Runnable set the content view to the real layout you want to use for this activity.



                                            For example:



                                            mHandler.post(new Runnable(){

                                            public void run() {
                                            setContentView(R.layout.my_layout);
                                            }
                                            });


                                            This is what I did, and I've found that it runs faster than showing the ProgressDialog and it's less intrusive and has a better look in my opinion.



                                            However, if you're wanting to use the ProgressDialog, then this answer isn't for you.






                                            share|improve this answer
























                                            • This solution is elegant in a simple use case, but has drawbacks. You need to rebuild the full content view. setContentView(R.layout.my_layout); is not sufficient; you need to set all listeners, reset data, etc.

                                              – rds
                                              Mar 10 '11 at 23:40













                                            • @rds you are right. This is really only a solution to a simple case, or if you need to do some heavy lifting in your onCreate method before displaying your view.

                                              – Pzanno
                                              Mar 11 '11 at 19:12











                                            • I don't quite get it. Instead of settings listeners in the onCreate(), as we would typically do, we could set them up in the run(). Am I missing something here?

                                              – Code Poet
                                              Dec 11 '11 at 19:03














                                            8












                                            8








                                            8







                                            I faced this same problem, and I came up with a solution that didn't invole using the ProgressDialog and I get faster results.



                                            What I did was create a layout that has a ProgressBar in it.



                                            <?xml version="1.0" encoding="utf-8"?>
                                            <RelativeLayout
                                            xmlns:android="http://schemas.android.com/apk/res/android"
                                            android:layout_width="fill_parent"
                                            android:layout_height="fill_parent">
                                            <ProgressBar
                                            android:id="@+id/progressImage"
                                            android:layout_width="wrap_content"
                                            android:layout_height="wrap_content"
                                            android:layout_centerInParent="true"
                                            />
                                            </RelativeLayout>


                                            Then in the onCreate method do the following



                                            public void onCreate(Bundle icicle) {
                                            super.onCreate(icicle);
                                            setContentView(R.layout.progress);
                                            }


                                            Then do the long task in a thread, and when that's finished have a Runnable set the content view to the real layout you want to use for this activity.



                                            For example:



                                            mHandler.post(new Runnable(){

                                            public void run() {
                                            setContentView(R.layout.my_layout);
                                            }
                                            });


                                            This is what I did, and I've found that it runs faster than showing the ProgressDialog and it's less intrusive and has a better look in my opinion.



                                            However, if you're wanting to use the ProgressDialog, then this answer isn't for you.






                                            share|improve this answer













                                            I faced this same problem, and I came up with a solution that didn't invole using the ProgressDialog and I get faster results.



                                            What I did was create a layout that has a ProgressBar in it.



                                            <?xml version="1.0" encoding="utf-8"?>
                                            <RelativeLayout
                                            xmlns:android="http://schemas.android.com/apk/res/android"
                                            android:layout_width="fill_parent"
                                            android:layout_height="fill_parent">
                                            <ProgressBar
                                            android:id="@+id/progressImage"
                                            android:layout_width="wrap_content"
                                            android:layout_height="wrap_content"
                                            android:layout_centerInParent="true"
                                            />
                                            </RelativeLayout>


                                            Then in the onCreate method do the following



                                            public void onCreate(Bundle icicle) {
                                            super.onCreate(icicle);
                                            setContentView(R.layout.progress);
                                            }


                                            Then do the long task in a thread, and when that's finished have a Runnable set the content view to the real layout you want to use for this activity.



                                            For example:



                                            mHandler.post(new Runnable(){

                                            public void run() {
                                            setContentView(R.layout.my_layout);
                                            }
                                            });


                                            This is what I did, and I've found that it runs faster than showing the ProgressDialog and it's less intrusive and has a better look in my opinion.



                                            However, if you're wanting to use the ProgressDialog, then this answer isn't for you.







                                            share|improve this answer












                                            share|improve this answer



                                            share|improve this answer










                                            answered Sep 10 '10 at 14:45









                                            PzannoPzanno

                                            1,23511422




                                            1,23511422













                                            • This solution is elegant in a simple use case, but has drawbacks. You need to rebuild the full content view. setContentView(R.layout.my_layout); is not sufficient; you need to set all listeners, reset data, etc.

                                              – rds
                                              Mar 10 '11 at 23:40













                                            • @rds you are right. This is really only a solution to a simple case, or if you need to do some heavy lifting in your onCreate method before displaying your view.

                                              – Pzanno
                                              Mar 11 '11 at 19:12











                                            • I don't quite get it. Instead of settings listeners in the onCreate(), as we would typically do, we could set them up in the run(). Am I missing something here?

                                              – Code Poet
                                              Dec 11 '11 at 19:03



















                                            • This solution is elegant in a simple use case, but has drawbacks. You need to rebuild the full content view. setContentView(R.layout.my_layout); is not sufficient; you need to set all listeners, reset data, etc.

                                              – rds
                                              Mar 10 '11 at 23:40













                                            • @rds you are right. This is really only a solution to a simple case, or if you need to do some heavy lifting in your onCreate method before displaying your view.

                                              – Pzanno
                                              Mar 11 '11 at 19:12











                                            • I don't quite get it. Instead of settings listeners in the onCreate(), as we would typically do, we could set them up in the run(). Am I missing something here?

                                              – Code Poet
                                              Dec 11 '11 at 19:03

















                                            This solution is elegant in a simple use case, but has drawbacks. You need to rebuild the full content view. setContentView(R.layout.my_layout); is not sufficient; you need to set all listeners, reset data, etc.

                                            – rds
                                            Mar 10 '11 at 23:40







                                            This solution is elegant in a simple use case, but has drawbacks. You need to rebuild the full content view. setContentView(R.layout.my_layout); is not sufficient; you need to set all listeners, reset data, etc.

                                            – rds
                                            Mar 10 '11 at 23:40















                                            @rds you are right. This is really only a solution to a simple case, or if you need to do some heavy lifting in your onCreate method before displaying your view.

                                            – Pzanno
                                            Mar 11 '11 at 19:12





                                            @rds you are right. This is really only a solution to a simple case, or if you need to do some heavy lifting in your onCreate method before displaying your view.

                                            – Pzanno
                                            Mar 11 '11 at 19:12













                                            I don't quite get it. Instead of settings listeners in the onCreate(), as we would typically do, we could set them up in the run(). Am I missing something here?

                                            – Code Poet
                                            Dec 11 '11 at 19:03





                                            I don't quite get it. Instead of settings listeners in the onCreate(), as we would typically do, we could set them up in the run(). Am I missing something here?

                                            – Code Poet
                                            Dec 11 '11 at 19:03











                                            7














                                            I discovered a solution to this that I haven't yet seen elsewhere. You can use a custom application object that knows if you have background tasks going, instead of trying to do this in the activity that gets destroyed and recreated on orientation change. I blogged about this in here.






                                            share|improve this answer



















                                            • 1





                                              Creating a custom Application is normally used to maintain a global application state. I don't say it doesn't work it, but it seems over-complicated. From the doc "There is normally no need to subclass Application.". I largely prefer sonxurxo's answer.

                                              – rds
                                              Mar 10 '11 at 16:41
















                                            7














                                            I discovered a solution to this that I haven't yet seen elsewhere. You can use a custom application object that knows if you have background tasks going, instead of trying to do this in the activity that gets destroyed and recreated on orientation change. I blogged about this in here.






                                            share|improve this answer



















                                            • 1





                                              Creating a custom Application is normally used to maintain a global application state. I don't say it doesn't work it, but it seems over-complicated. From the doc "There is normally no need to subclass Application.". I largely prefer sonxurxo's answer.

                                              – rds
                                              Mar 10 '11 at 16:41














                                            7












                                            7








                                            7







                                            I discovered a solution to this that I haven't yet seen elsewhere. You can use a custom application object that knows if you have background tasks going, instead of trying to do this in the activity that gets destroyed and recreated on orientation change. I blogged about this in here.






                                            share|improve this answer













                                            I discovered a solution to this that I haven't yet seen elsewhere. You can use a custom application object that knows if you have background tasks going, instead of trying to do this in the activity that gets destroyed and recreated on orientation change. I blogged about this in here.







                                            share|improve this answer












                                            share|improve this answer



                                            share|improve this answer










                                            answered May 17 '10 at 16:20









                                            Heikki ToivonenHeikki Toivonen

                                            20.8k103542




                                            20.8k103542








                                            • 1





                                              Creating a custom Application is normally used to maintain a global application state. I don't say it doesn't work it, but it seems over-complicated. From the doc "There is normally no need to subclass Application.". I largely prefer sonxurxo's answer.

                                              – rds
                                              Mar 10 '11 at 16:41














                                            • 1





                                              Creating a custom Application is normally used to maintain a global application state. I don't say it doesn't work it, but it seems over-complicated. From the doc "There is normally no need to subclass Application.". I largely prefer sonxurxo's answer.

                                              – rds
                                              Mar 10 '11 at 16:41








                                            1




                                            1





                                            Creating a custom Application is normally used to maintain a global application state. I don't say it doesn't work it, but it seems over-complicated. From the doc "There is normally no need to subclass Application.". I largely prefer sonxurxo's answer.

                                            – rds
                                            Mar 10 '11 at 16:41





                                            Creating a custom Application is normally used to maintain a global application state. I don't say it doesn't work it, but it seems over-complicated. From the doc "There is normally no need to subclass Application.". I largely prefer sonxurxo's answer.

                                            – rds
                                            Mar 10 '11 at 16:41











                                            7














                                            I going to contribute my approach to handling this rotation issue. This may not be relevant to OP as he's not using AsyncTask, but maybe others will find it useful. It's pretty simple but it seems to do the job for me:



                                            I have a login activity with a nested AsyncTask class called BackgroundLoginTask.



                                            In my BackgroundLoginTask I don't do anything out of the ordinary except to add a null check upon calling ProgressDialog's dismiss:



                                            @Override
                                            protected void onPostExecute(Boolean result)
                                            {
                                            if (pleaseWaitDialog != null)
                                            pleaseWaitDialog.dismiss();
                                            [...]
                                            }


                                            This is to handle the case where the background task finishes while the Activity is not visible and, therefore, the progress dialog has already been dismissed by the onPause() method.



                                            Next, in my parent Activity class, I create global static handles to my AsyncTask class and my ProgressDialog (the AsyncTask, being nested, can access these variables):



                                            private static BackgroundLoginTask backgroundLoginTask;
                                            private static ProgressDialog pleaseWaitDialog;


                                            This serves two purposes: First, it allows my Activity to always access the AsyncTask object even from a new, post-rotated activity. Second, it allows my BackgroundLoginTask to access and dismiss the ProgressDialog even after a rotate.



                                            Next, I add this to onPause(), causing the progress dialog to disappear when our Activity is leaving the foreground (preventing that ugly "force close" crash):



                                                if (pleaseWaitDialog != null)
                                            pleaseWaitDialog.dismiss();


                                            Finally, I have the following in my onResume() method:



                                            if ((backgroundLoginTask != null) && (backgroundLoginTask.getStatus() == Status.RUNNING))
                                            {
                                            if (pleaseWaitDialog != null)
                                            pleaseWaitDialog.show();
                                            }


                                            This allows the Dialog to reappear after the Activity is recreated.



                                            Here is the entire class:



                                            public class NSFkioskLoginActivity extends NSFkioskBaseActivity {
                                            private static BackgroundLoginTask backgroundLoginTask;
                                            private static ProgressDialog pleaseWaitDialog;
                                            private Controller cont;

                                            // This is the app entry point.
                                            /** Called when the activity is first created. */
                                            @Override
                                            public void onCreate(Bundle savedInstanceState) {
                                            super.onCreate(savedInstanceState);

                                            if (CredentialsAvailableAndValidated())
                                            {
                                            //Go to main menu and don't run rest of onCreate method.
                                            gotoMainMenu();
                                            return;
                                            }
                                            setContentView(R.layout.login);
                                            populateStoredCredentials();
                                            }

                                            //Save current progress to options when app is leaving foreground
                                            @Override
                                            public void onPause()
                                            {
                                            super.onPause();
                                            saveCredentialsToPreferences(false);
                                            //Get rid of progress dialog in the event of a screen rotation. Prevents a crash.
                                            if (pleaseWaitDialog != null)
                                            pleaseWaitDialog.dismiss();
                                            }

                                            @Override
                                            public void onResume()
                                            {
                                            super.onResume();
                                            if ((backgroundLoginTask != null) && (backgroundLoginTask.getStatus() == Status.RUNNING))
                                            {
                                            if (pleaseWaitDialog != null)
                                            pleaseWaitDialog.show();
                                            }
                                            }

                                            /**
                                            * Go to main menu, finishing this activity
                                            */
                                            private void gotoMainMenu()
                                            {
                                            startActivity(new Intent(getApplicationContext(), NSFkioskMainMenuActivity.class));
                                            finish();
                                            }

                                            /**
                                            *
                                            * @param setValidatedBooleanTrue If set true, method will set CREDS_HAVE_BEEN_VALIDATED to true in addition to saving username/password.
                                            */
                                            private void saveCredentialsToPreferences(boolean setValidatedBooleanTrue)
                                            {
                                            SharedPreferences settings = getSharedPreferences(APP_PREFERENCES, MODE_PRIVATE);
                                            SharedPreferences.Editor prefEditor = settings.edit();
                                            EditText usernameText = (EditText) findViewById(R.id.editTextUsername);
                                            EditText pswText = (EditText) findViewById(R.id.editTextPassword);
                                            prefEditor.putString(USERNAME, usernameText.getText().toString());
                                            prefEditor.putString(PASSWORD, pswText.getText().toString());
                                            if (setValidatedBooleanTrue)
                                            prefEditor.putBoolean(CREDS_HAVE_BEEN_VALIDATED, true);
                                            prefEditor.commit();
                                            }

                                            /**
                                            * Checks if user is already signed in
                                            */
                                            private boolean CredentialsAvailableAndValidated() {
                                            SharedPreferences settings = getSharedPreferences(APP_PREFERENCES,
                                            MODE_PRIVATE);
                                            if (settings.contains(USERNAME) && settings.contains(PASSWORD) && settings.getBoolean(CREDS_HAVE_BEEN_VALIDATED, false) == true)
                                            return true;
                                            else
                                            return false;
                                            }

                                            //Populate stored credentials, if any available
                                            private void populateStoredCredentials()
                                            {
                                            SharedPreferences settings = getSharedPreferences(APP_PREFERENCES,
                                            MODE_PRIVATE);
                                            settings.getString(USERNAME, "");
                                            EditText usernameText = (EditText) findViewById(R.id.editTextUsername);
                                            usernameText.setText(settings.getString(USERNAME, ""));
                                            EditText pswText = (EditText) findViewById(R.id.editTextPassword);
                                            pswText.setText(settings.getString(PASSWORD, ""));
                                            }

                                            /**
                                            * Validate credentials in a seperate thread, displaying a progress circle in the meantime
                                            * If successful, save credentials in preferences and proceed to main menu activity
                                            * If not, display an error message
                                            */
                                            public void loginButtonClick(View view)
                                            {
                                            if (phoneIsOnline())
                                            {
                                            EditText usernameText = (EditText) findViewById(R.id.editTextUsername);
                                            EditText pswText = (EditText) findViewById(R.id.editTextPassword);
                                            //Call background task worker with username and password params
                                            backgroundLoginTask = new BackgroundLoginTask();
                                            backgroundLoginTask.execute(usernameText.getText().toString(), pswText.getText().toString());
                                            }
                                            else
                                            {
                                            //Display toast informing of no internet access
                                            String notOnlineMessage = getResources().getString(R.string.noNetworkAccessAvailable);
                                            Toast toast = Toast.makeText(getApplicationContext(), notOnlineMessage, Toast.LENGTH_SHORT);
                                            toast.show();
                                            }
                                            }

                                            /**
                                            *
                                            * Takes two params: username and password
                                            *
                                            */
                                            public class BackgroundLoginTask extends AsyncTask<Object, String, Boolean>
                                            {
                                            private Exception e = null;

                                            @Override
                                            protected void onPreExecute()
                                            {
                                            cont = Controller.getInstance();
                                            //Show progress dialog
                                            String pleaseWait = getResources().getString(R.string.pleaseWait);
                                            String commWithServer = getResources().getString(R.string.communicatingWithServer);
                                            if (pleaseWaitDialog == null)
                                            pleaseWaitDialog= ProgressDialog.show(NSFkioskLoginActivity.this, pleaseWait, commWithServer, true);

                                            }

                                            @Override
                                            protected Boolean doInBackground(Object... params)
                                            {
                                            try {
                                            //Returns true if credentials were valid. False if not. Exception if server could not be reached.
                                            return cont.validateCredentials((String)params[0], (String)params[1]);
                                            } catch (Exception e) {
                                            this.e=e;
                                            return false;
                                            }
                                            }

                                            /**
                                            * result is passed from doInBackground. Indicates whether credentials were validated.
                                            */
                                            @Override
                                            protected void onPostExecute(Boolean result)
                                            {
                                            //Hide progress dialog and handle exceptions
                                            //Progress dialog may be null if rotation has been switched
                                            if (pleaseWaitDialog != null)
                                            {
                                            pleaseWaitDialog.dismiss();
                                            pleaseWaitDialog = null;
                                            }

                                            if (e != null)
                                            {
                                            //Show toast with exception text
                                            String networkError = getResources().getString(R.string.serverErrorException);
                                            Toast toast = Toast.makeText(getApplicationContext(), networkError, Toast.LENGTH_SHORT);
                                            toast.show();
                                            }
                                            else
                                            {
                                            if (result == true)
                                            {
                                            saveCredentialsToPreferences(true);
                                            gotoMainMenu();
                                            }
                                            else
                                            {
                                            String toastText = getResources().getString(R.string.invalidCredentialsEntered);
                                            Toast toast = Toast.makeText(getApplicationContext(), toastText, Toast.LENGTH_SHORT);
                                            toast.show();
                                            }
                                            }
                                            }

                                            }
                                            }


                                            I am by no means a seasoned Android developer, so feel free to comment.






                                            share|improve this answer





















                                            • 1





                                              Interesting! Especially for those of us using AsyncTask. Just tried out your solution, and it seems to mostly work. There's one problem: the ProgressDialog seems to terminate a little early after a rotation WHILE the ProgressDialog is still active. I'm going to play around to see exactly what's happening and how to remedy it. But I'm no longer getting those crashes!

                                              – Scott Biggs
                                              Feb 7 '12 at 7:00






                                            • 1





                                              Found a fix. It seems that the problem here is the static ProgressDialog. When rotations interrupt the ProgressDialog, it sometimes gets its .dismiss() method called after it is restarted in the new Activity. By making the ProgressDialog created with each Activity, we ensure that this new ProgressDialog isn't killed along with the old Activity. I also made sure that the ProgressDialog is set to null whenever it's dismissed (to aid garbage collection). So we have a solution here! Cheers to those using AsyncTask!

                                              – Scott Biggs
                                              Feb 8 '12 at 6:06
















                                            7














                                            I going to contribute my approach to handling this rotation issue. This may not be relevant to OP as he's not using AsyncTask, but maybe others will find it useful. It's pretty simple but it seems to do the job for me:



                                            I have a login activity with a nested AsyncTask class called BackgroundLoginTask.



                                            In my BackgroundLoginTask I don't do anything out of the ordinary except to add a null check upon calling ProgressDialog's dismiss:



                                            @Override
                                            protected void onPostExecute(Boolean result)
                                            {
                                            if (pleaseWaitDialog != null)
                                            pleaseWaitDialog.dismiss();
                                            [...]
                                            }


                                            This is to handle the case where the background task finishes while the Activity is not visible and, therefore, the progress dialog has already been dismissed by the onPause() method.



                                            Next, in my parent Activity class, I create global static handles to my AsyncTask class and my ProgressDialog (the AsyncTask, being nested, can access these variables):



                                            private static BackgroundLoginTask backgroundLoginTask;
                                            private static ProgressDialog pleaseWaitDialog;


                                            This serves two purposes: First, it allows my Activity to always access the AsyncTask object even from a new, post-rotated activity. Second, it allows my BackgroundLoginTask to access and dismiss the ProgressDialog even after a rotate.



                                            Next, I add this to onPause(), causing the progress dialog to disappear when our Activity is leaving the foreground (preventing that ugly "force close" crash):



                                                if (pleaseWaitDialog != null)
                                            pleaseWaitDialog.dismiss();


                                            Finally, I have the following in my onResume() method:



                                            if ((backgroundLoginTask != null) && (backgroundLoginTask.getStatus() == Status.RUNNING))
                                            {
                                            if (pleaseWaitDialog != null)
                                            pleaseWaitDialog.show();
                                            }


                                            This allows the Dialog to reappear after the Activity is recreated.



                                            Here is the entire class:



                                            public class NSFkioskLoginActivity extends NSFkioskBaseActivity {
                                            private static BackgroundLoginTask backgroundLoginTask;
                                            private static ProgressDialog pleaseWaitDialog;
                                            private Controller cont;

                                            // This is the app entry point.
                                            /** Called when the activity is first created. */
                                            @Override
                                            public void onCreate(Bundle savedInstanceState) {
                                            super.onCreate(savedInstanceState);

                                            if (CredentialsAvailableAndValidated())
                                            {
                                            //Go to main menu and don't run rest of onCreate method.
                                            gotoMainMenu();
                                            return;
                                            }
                                            setContentView(R.layout.login);
                                            populateStoredCredentials();
                                            }

                                            //Save current progress to options when app is leaving foreground
                                            @Override
                                            public void onPause()
                                            {
                                            super.onPause();
                                            saveCredentialsToPreferences(false);
                                            //Get rid of progress dialog in the event of a screen rotation. Prevents a crash.
                                            if (pleaseWaitDialog != null)
                                            pleaseWaitDialog.dismiss();
                                            }

                                            @Override
                                            public void onResume()
                                            {
                                            super.onResume();
                                            if ((backgroundLoginTask != null) && (backgroundLoginTask.getStatus() == Status.RUNNING))
                                            {
                                            if (pleaseWaitDialog != null)
                                            pleaseWaitDialog.show();
                                            }
                                            }

                                            /**
                                            * Go to main menu, finishing this activity
                                            */
                                            private void gotoMainMenu()
                                            {
                                            startActivity(new Intent(getApplicationContext(), NSFkioskMainMenuActivity.class));
                                            finish();
                                            }

                                            /**
                                            *
                                            * @param setValidatedBooleanTrue If set true, method will set CREDS_HAVE_BEEN_VALIDATED to true in addition to saving username/password.
                                            */
                                            private void saveCredentialsToPreferences(boolean setValidatedBooleanTrue)
                                            {
                                            SharedPreferences settings = getSharedPreferences(APP_PREFERENCES, MODE_PRIVATE);
                                            SharedPreferences.Editor prefEditor = settings.edit();
                                            EditText usernameText = (EditText) findViewById(R.id.editTextUsername);
                                            EditText pswText = (EditText) findViewById(R.id.editTextPassword);
                                            prefEditor.putString(USERNAME, usernameText.getText().toString());
                                            prefEditor.putString(PASSWORD, pswText.getText().toString());
                                            if (setValidatedBooleanTrue)
                                            prefEditor.putBoolean(CREDS_HAVE_BEEN_VALIDATED, true);
                                            prefEditor.commit();
                                            }

                                            /**
                                            * Checks if user is already signed in
                                            */
                                            private boolean CredentialsAvailableAndValidated() {
                                            SharedPreferences settings = getSharedPreferences(APP_PREFERENCES,
                                            MODE_PRIVATE);
                                            if (settings.contains(USERNAME) && settings.contains(PASSWORD) && settings.getBoolean(CREDS_HAVE_BEEN_VALIDATED, false) == true)
                                            return true;
                                            else
                                            return false;
                                            }

                                            //Populate stored credentials, if any available
                                            private void populateStoredCredentials()
                                            {
                                            SharedPreferences settings = getSharedPreferences(APP_PREFERENCES,
                                            MODE_PRIVATE);
                                            settings.getString(USERNAME, "");
                                            EditText usernameText = (EditText) findViewById(R.id.editTextUsername);
                                            usernameText.setText(settings.getString(USERNAME, ""));
                                            EditText pswText = (EditText) findViewById(R.id.editTextPassword);
                                            pswText.setText(settings.getString(PASSWORD, ""));
                                            }

                                            /**
                                            * Validate credentials in a seperate thread, displaying a progress circle in the meantime
                                            * If successful, save credentials in preferences and proceed to main menu activity
                                            * If not, display an error message
                                            */
                                            public void loginButtonClick(View view)
                                            {
                                            if (phoneIsOnline())
                                            {
                                            EditText usernameText = (EditText) findViewById(R.id.editTextUsername);
                                            EditText pswText = (EditText) findViewById(R.id.editTextPassword);
                                            //Call background task worker with username and password params
                                            backgroundLoginTask = new BackgroundLoginTask();
                                            backgroundLoginTask.execute(usernameText.getText().toString(), pswText.getText().toString());
                                            }
                                            else
                                            {
                                            //Display toast informing of no internet access
                                            String notOnlineMessage = getResources().getString(R.string.noNetworkAccessAvailable);
                                            Toast toast = Toast.makeText(getApplicationContext(), notOnlineMessage, Toast.LENGTH_SHORT);
                                            toast.show();
                                            }
                                            }

                                            /**
                                            *
                                            * Takes two params: username and password
                                            *
                                            */
                                            public class BackgroundLoginTask extends AsyncTask<Object, String, Boolean>
                                            {
                                            private Exception e = null;

                                            @Override
                                            protected void onPreExecute()
                                            {
                                            cont = Controller.getInstance();
                                            //Show progress dialog
                                            String pleaseWait = getResources().getString(R.string.pleaseWait);
                                            String commWithServer = getResources().getString(R.string.communicatingWithServer);
                                            if (pleaseWaitDialog == null)
                                            pleaseWaitDialog= ProgressDialog.show(NSFkioskLoginActivity.this, pleaseWait, commWithServer, true);

                                            }

                                            @Override
                                            protected Boolean doInBackground(Object... params)
                                            {
                                            try {
                                            //Returns true if credentials were valid. False if not. Exception if server could not be reached.
                                            return cont.validateCredentials((String)params[0], (String)params[1]);
                                            } catch (Exception e) {
                                            this.e=e;
                                            return false;
                                            }
                                            }

                                            /**
                                            * result is passed from doInBackground. Indicates whether credentials were validated.
                                            */
                                            @Override
                                            protected void onPostExecute(Boolean result)
                                            {
                                            //Hide progress dialog and handle exceptions
                                            //Progress dialog may be null if rotation has been switched
                                            if (pleaseWaitDialog != null)
                                            {
                                            pleaseWaitDialog.dismiss();
                                            pleaseWaitDialog = null;
                                            }

                                            if (e != null)
                                            {
                                            //Show toast with exception text
                                            String networkError = getResources().getString(R.string.serverErrorException);
                                            Toast toast = Toast.makeText(getApplicationContext(), networkError, Toast.LENGTH_SHORT);
                                            toast.show();
                                            }
                                            else
                                            {
                                            if (result == true)
                                            {
                                            saveCredentialsToPreferences(true);
                                            gotoMainMenu();
                                            }
                                            else
                                            {
                                            String toastText = getResources().getString(R.string.invalidCredentialsEntered);
                                            Toast toast = Toast.makeText(getApplicationContext(), toastText, Toast.LENGTH_SHORT);
                                            toast.show();
                                            }
                                            }
                                            }

                                            }
                                            }


                                            I am by no means a seasoned Android developer, so feel free to comment.






                                            share|improve this answer





















                                            • 1





                                              Interesting! Especially for those of us using AsyncTask. Just tried out your solution, and it seems to mostly work. There's one problem: the ProgressDialog seems to terminate a little early after a rotation WHILE the ProgressDialog is still active. I'm going to play around to see exactly what's happening and how to remedy it. But I'm no longer getting those crashes!

                                              – Scott Biggs
                                              Feb 7 '12 at 7:00






                                            • 1





                                              Found a fix. It seems that the problem here is the static ProgressDialog. When rotations interrupt the ProgressDialog, it sometimes gets its .dismiss() method called after it is restarted in the new Activity. By making the ProgressDialog created with each Activity, we ensure that this new ProgressDialog isn't killed along with the old Activity. I also made sure that the ProgressDialog is set to null whenever it's dismissed (to aid garbage collection). So we have a solution here! Cheers to those using AsyncTask!

                                              – Scott Biggs
                                              Feb 8 '12 at 6:06














                                            7












                                            7








                                            7







                                            I going to contribute my approach to handling this rotation issue. This may not be relevant to OP as he's not using AsyncTask, but maybe others will find it useful. It's pretty simple but it seems to do the job for me:



                                            I have a login activity with a nested AsyncTask class called BackgroundLoginTask.



                                            In my BackgroundLoginTask I don't do anything out of the ordinary except to add a null check upon calling ProgressDialog's dismiss:



                                            @Override
                                            protected void onPostExecute(Boolean result)
                                            {
                                            if (pleaseWaitDialog != null)
                                            pleaseWaitDialog.dismiss();
                                            [...]
                                            }


                                            This is to handle the case where the background task finishes while the Activity is not visible and, therefore, the progress dialog has already been dismissed by the onPause() method.



                                            Next, in my parent Activity class, I create global static handles to my AsyncTask class and my ProgressDialog (the AsyncTask, being nested, can access these variables):



                                            private static BackgroundLoginTask backgroundLoginTask;
                                            private static ProgressDialog pleaseWaitDialog;


                                            This serves two purposes: First, it allows my Activity to always access the AsyncTask object even from a new, post-rotated activity. Second, it allows my BackgroundLoginTask to access and dismiss the ProgressDialog even after a rotate.



                                            Next, I add this to onPause(), causing the progress dialog to disappear when our Activity is leaving the foreground (preventing that ugly "force close" crash):



                                                if (pleaseWaitDialog != null)
                                            pleaseWaitDialog.dismiss();


                                            Finally, I have the following in my onResume() method:



                                            if ((backgroundLoginTask != null) && (backgroundLoginTask.getStatus() == Status.RUNNING))
                                            {
                                            if (pleaseWaitDialog != null)
                                            pleaseWaitDialog.show();
                                            }


                                            This allows the Dialog to reappear after the Activity is recreated.



                                            Here is the entire class:



                                            public class NSFkioskLoginActivity extends NSFkioskBaseActivity {
                                            private static BackgroundLoginTask backgroundLoginTask;
                                            private static ProgressDialog pleaseWaitDialog;
                                            private Controller cont;

                                            // This is the app entry point.
                                            /** Called when the activity is first created. */
                                            @Override
                                            public void onCreate(Bundle savedInstanceState) {
                                            super.onCreate(savedInstanceState);

                                            if (CredentialsAvailableAndValidated())
                                            {
                                            //Go to main menu and don't run rest of onCreate method.
                                            gotoMainMenu();
                                            return;
                                            }
                                            setContentView(R.layout.login);
                                            populateStoredCredentials();
                                            }

                                            //Save current progress to options when app is leaving foreground
                                            @Override
                                            public void onPause()
                                            {
                                            super.onPause();
                                            saveCredentialsToPreferences(false);
                                            //Get rid of progress dialog in the event of a screen rotation. Prevents a crash.
                                            if (pleaseWaitDialog != null)
                                            pleaseWaitDialog.dismiss();
                                            }

                                            @Override
                                            public void onResume()
                                            {
                                            super.onResume();
                                            if ((backgroundLoginTask != null) && (backgroundLoginTask.getStatus() == Status.RUNNING))
                                            {
                                            if (pleaseWaitDialog != null)
                                            pleaseWaitDialog.show();
                                            }
                                            }

                                            /**
                                            * Go to main menu, finishing this activity
                                            */
                                            private void gotoMainMenu()
                                            {
                                            startActivity(new Intent(getApplicationContext(), NSFkioskMainMenuActivity.class));
                                            finish();
                                            }

                                            /**
                                            *
                                            * @param setValidatedBooleanTrue If set true, method will set CREDS_HAVE_BEEN_VALIDATED to true in addition to saving username/password.
                                            */
                                            private void saveCredentialsToPreferences(boolean setValidatedBooleanTrue)
                                            {
                                            SharedPreferences settings = getSharedPreferences(APP_PREFERENCES, MODE_PRIVATE);
                                            SharedPreferences.Editor prefEditor = settings.edit();
                                            EditText usernameText = (EditText) findViewById(R.id.editTextUsername);
                                            EditText pswText = (EditText) findViewById(R.id.editTextPassword);
                                            prefEditor.putString(USERNAME, usernameText.getText().toString());
                                            prefEditor.putString(PASSWORD, pswText.getText().toString());
                                            if (setValidatedBooleanTrue)
                                            prefEditor.putBoolean(CREDS_HAVE_BEEN_VALIDATED, true);
                                            prefEditor.commit();
                                            }

                                            /**
                                            * Checks if user is already signed in
                                            */
                                            private boolean CredentialsAvailableAndValidated() {
                                            SharedPreferences settings = getSharedPreferences(APP_PREFERENCES,
                                            MODE_PRIVATE);
                                            if (settings.contains(USERNAME) && settings.contains(PASSWORD) && settings.getBoolean(CREDS_HAVE_BEEN_VALIDATED, false) == true)
                                            return true;
                                            else
                                            return false;
                                            }

                                            //Populate stored credentials, if any available
                                            private void populateStoredCredentials()
                                            {
                                            SharedPreferences settings = getSharedPreferences(APP_PREFERENCES,
                                            MODE_PRIVATE);
                                            settings.getString(USERNAME, "");
                                            EditText usernameText = (EditText) findViewById(R.id.editTextUsername);
                                            usernameText.setText(settings.getString(USERNAME, ""));
                                            EditText pswText = (EditText) findViewById(R.id.editTextPassword);
                                            pswText.setText(settings.getString(PASSWORD, ""));
                                            }

                                            /**
                                            * Validate credentials in a seperate thread, displaying a progress circle in the meantime
                                            * If successful, save credentials in preferences and proceed to main menu activity
                                            * If not, display an error message
                                            */
                                            public void loginButtonClick(View view)
                                            {
                                            if (phoneIsOnline())
                                            {
                                            EditText usernameText = (EditText) findViewById(R.id.editTextUsername);
                                            EditText pswText = (EditText) findViewById(R.id.editTextPassword);
                                            //Call background task worker with username and password params
                                            backgroundLoginTask = new BackgroundLoginTask();
                                            backgroundLoginTask.execute(usernameText.getText().toString(), pswText.getText().toString());
                                            }
                                            else
                                            {
                                            //Display toast informing of no internet access
                                            String notOnlineMessage = getResources().getString(R.string.noNetworkAccessAvailable);
                                            Toast toast = Toast.makeText(getApplicationContext(), notOnlineMessage, Toast.LENGTH_SHORT);
                                            toast.show();
                                            }
                                            }

                                            /**
                                            *
                                            * Takes two params: username and password
                                            *
                                            */
                                            public class BackgroundLoginTask extends AsyncTask<Object, String, Boolean>
                                            {
                                            private Exception e = null;

                                            @Override
                                            protected void onPreExecute()
                                            {
                                            cont = Controller.getInstance();
                                            //Show progress dialog
                                            String pleaseWait = getResources().getString(R.string.pleaseWait);
                                            String commWithServer = getResources().getString(R.string.communicatingWithServer);
                                            if (pleaseWaitDialog == null)
                                            pleaseWaitDialog= ProgressDialog.show(NSFkioskLoginActivity.this, pleaseWait, commWithServer, true);

                                            }

                                            @Override
                                            protected Boolean doInBackground(Object... params)
                                            {
                                            try {
                                            //Returns true if credentials were valid. False if not. Exception if server could not be reached.
                                            return cont.validateCredentials((String)params[0], (String)params[1]);
                                            } catch (Exception e) {
                                            this.e=e;
                                            return false;
                                            }
                                            }

                                            /**
                                            * result is passed from doInBackground. Indicates whether credentials were validated.
                                            */
                                            @Override
                                            protected void onPostExecute(Boolean result)
                                            {
                                            //Hide progress dialog and handle exceptions
                                            //Progress dialog may be null if rotation has been switched
                                            if (pleaseWaitDialog != null)
                                            {
                                            pleaseWaitDialog.dismiss();
                                            pleaseWaitDialog = null;
                                            }

                                            if (e != null)
                                            {
                                            //Show toast with exception text
                                            String networkError = getResources().getString(R.string.serverErrorException);
                                            Toast toast = Toast.makeText(getApplicationContext(), networkError, Toast.LENGTH_SHORT);
                                            toast.show();
                                            }
                                            else
                                            {
                                            if (result == true)
                                            {
                                            saveCredentialsToPreferences(true);
                                            gotoMainMenu();
                                            }
                                            else
                                            {
                                            String toastText = getResources().getString(R.string.invalidCredentialsEntered);
                                            Toast toast = Toast.makeText(getApplicationContext(), toastText, Toast.LENGTH_SHORT);
                                            toast.show();
                                            }
                                            }
                                            }

                                            }
                                            }


                                            I am by no means a seasoned Android developer, so feel free to comment.






                                            share|improve this answer















                                            I going to contribute my approach to handling this rotation issue. This may not be relevant to OP as he's not using AsyncTask, but maybe others will find it useful. It's pretty simple but it seems to do the job for me:



                                            I have a login activity with a nested AsyncTask class called BackgroundLoginTask.



                                            In my BackgroundLoginTask I don't do anything out of the ordinary except to add a null check upon calling ProgressDialog's dismiss:



                                            @Override
                                            protected void onPostExecute(Boolean result)
                                            {
                                            if (pleaseWaitDialog != null)
                                            pleaseWaitDialog.dismiss();
                                            [...]
                                            }


                                            This is to handle the case where the background task finishes while the Activity is not visible and, therefore, the progress dialog has already been dismissed by the onPause() method.



                                            Next, in my parent Activity class, I create global static handles to my AsyncTask class and my ProgressDialog (the AsyncTask, being nested, can access these variables):



                                            private static BackgroundLoginTask backgroundLoginTask;
                                            private static ProgressDialog pleaseWaitDialog;


                                            This serves two purposes: First, it allows my Activity to always access the AsyncTask object even from a new, post-rotated activity. Second, it allows my BackgroundLoginTask to access and dismiss the ProgressDialog even after a rotate.



                                            Next, I add this to onPause(), causing the progress dialog to disappear when our Activity is leaving the foreground (preventing that ugly "force close" crash):



                                                if (pleaseWaitDialog != null)
                                            pleaseWaitDialog.dismiss();


                                            Finally, I have the following in my onResume() method:



                                            if ((backgroundLoginTask != null) && (backgroundLoginTask.getStatus() == Status.RUNNING))
                                            {
                                            if (pleaseWaitDialog != null)
                                            pleaseWaitDialog.show();
                                            }


                                            This allows the Dialog to reappear after the Activity is recreated.



                                            Here is the entire class:



                                            public class NSFkioskLoginActivity extends NSFkioskBaseActivity {
                                            private static BackgroundLoginTask backgroundLoginTask;
                                            private static ProgressDialog pleaseWaitDialog;
                                            private Controller cont;

                                            // This is the app entry point.
                                            /** Called when the activity is first created. */
                                            @Override
                                            public void onCreate(Bundle savedInstanceState) {
                                            super.onCreate(savedInstanceState);

                                            if (CredentialsAvailableAndValidated())
                                            {
                                            //Go to main menu and don't run rest of onCreate method.
                                            gotoMainMenu();
                                            return;
                                            }
                                            setContentView(R.layout.login);
                                            populateStoredCredentials();
                                            }

                                            //Save current progress to options when app is leaving foreground
                                            @Override
                                            public void onPause()
                                            {
                                            super.onPause();
                                            saveCredentialsToPreferences(false);
                                            //Get rid of progress dialog in the event of a screen rotation. Prevents a crash.
                                            if (pleaseWaitDialog != null)
                                            pleaseWaitDialog.dismiss();
                                            }

                                            @Override
                                            public void onResume()
                                            {
                                            super.onResume();
                                            if ((backgroundLoginTask != null) && (backgroundLoginTask.getStatus() == Status.RUNNING))
                                            {
                                            if (pleaseWaitDialog != null)
                                            pleaseWaitDialog.show();
                                            }
                                            }

                                            /**
                                            * Go to main menu, finishing this activity
                                            */
                                            private void gotoMainMenu()
                                            {
                                            startActivity(new Intent(getApplicationContext(), NSFkioskMainMenuActivity.class));
                                            finish();
                                            }

                                            /**
                                            *
                                            * @param setValidatedBooleanTrue If set true, method will set CREDS_HAVE_BEEN_VALIDATED to true in addition to saving username/password.
                                            */
                                            private void saveCredentialsToPreferences(boolean setValidatedBooleanTrue)
                                            {
                                            SharedPreferences settings = getSharedPreferences(APP_PREFERENCES, MODE_PRIVATE);
                                            SharedPreferences.Editor prefEditor = settings.edit();
                                            EditText usernameText = (EditText) findViewById(R.id.editTextUsername);
                                            EditText pswText = (EditText) findViewById(R.id.editTextPassword);
                                            prefEditor.putString(USERNAME, usernameText.getText().toString());
                                            prefEditor.putString(PASSWORD, pswText.getText().toString());
                                            if (setValidatedBooleanTrue)
                                            prefEditor.putBoolean(CREDS_HAVE_BEEN_VALIDATED, true);
                                            prefEditor.commit();
                                            }

                                            /**
                                            * Checks if user is already signed in
                                            */
                                            private boolean CredentialsAvailableAndValidated() {
                                            SharedPreferences settings = getSharedPreferences(APP_PREFERENCES,
                                            MODE_PRIVATE);
                                            if (settings.contains(USERNAME) && settings.contains(PASSWORD) && settings.getBoolean(CREDS_HAVE_BEEN_VALIDATED, false) == true)
                                            return true;
                                            else
                                            return false;
                                            }

                                            //Populate stored credentials, if any available
                                            private void populateStoredCredentials()
                                            {
                                            SharedPreferences settings = getSharedPreferences(APP_PREFERENCES,
                                            MODE_PRIVATE);
                                            settings.getString(USERNAME, "");
                                            EditText usernameText = (EditText) findViewById(R.id.editTextUsername);
                                            usernameText.setText(settings.getString(USERNAME, ""));
                                            EditText pswText = (EditText) findViewById(R.id.editTextPassword);
                                            pswText.setText(settings.getString(PASSWORD, ""));
                                            }

                                            /**
                                            * Validate credentials in a seperate thread, displaying a progress circle in the meantime
                                            * If successful, save credentials in preferences and proceed to main menu activity
                                            * If not, display an error message
                                            */
                                            public void loginButtonClick(View view)
                                            {
                                            if (phoneIsOnline())
                                            {
                                            EditText usernameText = (EditText) findViewById(R.id.editTextUsername);
                                            EditText pswText = (EditText) findViewById(R.id.editTextPassword);
                                            //Call background task worker with username and password params
                                            backgroundLoginTask = new BackgroundLoginTask();
                                            backgroundLoginTask.execute(usernameText.getText().toString(), pswText.getText().toString());
                                            }
                                            else
                                            {
                                            //Display toast informing of no internet access
                                            String notOnlineMessage = getResources().getString(R.string.noNetworkAccessAvailable);
                                            Toast toast = Toast.makeText(getApplicationContext(), notOnlineMessage, Toast.LENGTH_SHORT);
                                            toast.show();
                                            }
                                            }

                                            /**
                                            *
                                            * Takes two params: username and password
                                            *
                                            */
                                            public class BackgroundLoginTask extends AsyncTask<Object, String, Boolean>
                                            {
                                            private Exception e = null;

                                            @Override
                                            protected void onPreExecute()
                                            {
                                            cont = Controller.getInstance();
                                            //Show progress dialog
                                            String pleaseWait = getResources().getString(R.string.pleaseWait);
                                            String commWithServer = getResources().getString(R.string.communicatingWithServer);
                                            if (pleaseWaitDialog == null)
                                            pleaseWaitDialog= ProgressDialog.show(NSFkioskLoginActivity.this, pleaseWait, commWithServer, true);

                                            }

                                            @Override
                                            protected Boolean doInBackground(Object... params)
                                            {
                                            try {
                                            //Returns true if credentials were valid. False if not. Exception if server could not be reached.
                                            return cont.validateCredentials((String)params[0], (String)params[1]);
                                            } catch (Exception e) {
                                            this.e=e;
                                            return false;
                                            }
                                            }

                                            /**
                                            * result is passed from doInBackground. Indicates whether credentials were validated.
                                            */
                                            @Override
                                            protected void onPostExecute(Boolean result)
                                            {
                                            //Hide progress dialog and handle exceptions
                                            //Progress dialog may be null if rotation has been switched
                                            if (pleaseWaitDialog != null)
                                            {
                                            pleaseWaitDialog.dismiss();
                                            pleaseWaitDialog = null;
                                            }

                                            if (e != null)
                                            {
                                            //Show toast with exception text
                                            String networkError = getResources().getString(R.string.serverErrorException);
                                            Toast toast = Toast.makeText(getApplicationContext(), networkError, Toast.LENGTH_SHORT);
                                            toast.show();
                                            }
                                            else
                                            {
                                            if (result == true)
                                            {
                                            saveCredentialsToPreferences(true);
                                            gotoMainMenu();
                                            }
                                            else
                                            {
                                            String toastText = getResources().getString(R.string.invalidCredentialsEntered);
                                            Toast toast = Toast.makeText(getApplicationContext(), toastText, Toast.LENGTH_SHORT);
                                            toast.show();
                                            }
                                            }
                                            }

                                            }
                                            }


                                            I am by no means a seasoned Android developer, so feel free to comment.







                                            share|improve this answer














                                            share|improve this answer



                                            share|improve this answer








                                            edited Apr 20 '15 at 16:18









                                            Catalina

                                            898923




                                            898923










                                            answered Aug 13 '11 at 15:31









                                            AndersAnders

                                            68621119




                                            68621119








                                            • 1





                                              Interesting! Especially for those of us using AsyncTask. Just tried out your solution, and it seems to mostly work. There's one problem: the ProgressDialog seems to terminate a little early after a rotation WHILE the ProgressDialog is still active. I'm going to play around to see exactly what's happening and how to remedy it. But I'm no longer getting those crashes!

                                              – Scott Biggs
                                              Feb 7 '12 at 7:00






                                            • 1





                                              Found a fix. It seems that the problem here is the static ProgressDialog. When rotations interrupt the ProgressDialog, it sometimes gets its .dismiss() method called after it is restarted in the new Activity. By making the ProgressDialog created with each Activity, we ensure that this new ProgressDialog isn't killed along with the old Activity. I also made sure that the ProgressDialog is set to null whenever it's dismissed (to aid garbage collection). So we have a solution here! Cheers to those using AsyncTask!

                                              – Scott Biggs
                                              Feb 8 '12 at 6:06














                                            • 1





                                              Interesting! Especially for those of us using AsyncTask. Just tried out your solution, and it seems to mostly work. There's one problem: the ProgressDialog seems to terminate a little early after a rotation WHILE the ProgressDialog is still active. I'm going to play around to see exactly what's happening and how to remedy it. But I'm no longer getting those crashes!

                                              – Scott Biggs
                                              Feb 7 '12 at 7:00






                                            • 1





                                              Found a fix. It seems that the problem here is the static ProgressDialog. When rotations interrupt the ProgressDialog, it sometimes gets its .dismiss() method called after it is restarted in the new Activity. By making the ProgressDialog created with each Activity, we ensure that this new ProgressDialog isn't killed along with the old Activity. I also made sure that the ProgressDialog is set to null whenever it's dismissed (to aid garbage collection). So we have a solution here! Cheers to those using AsyncTask!

                                              – Scott Biggs
                                              Feb 8 '12 at 6:06








                                            1




                                            1





                                            Interesting! Especially for those of us using AsyncTask. Just tried out your solution, and it seems to mostly work. There's one problem: the ProgressDialog seems to terminate a little early after a rotation WHILE the ProgressDialog is still active. I'm going to play around to see exactly what's happening and how to remedy it. But I'm no longer getting those crashes!

                                            – Scott Biggs
                                            Feb 7 '12 at 7:00





                                            Interesting! Especially for those of us using AsyncTask. Just tried out your solution, and it seems to mostly work. There's one problem: the ProgressDialog seems to terminate a little early after a rotation WHILE the ProgressDialog is still active. I'm going to play around to see exactly what's happening and how to remedy it. But I'm no longer getting those crashes!

                                            – Scott Biggs
                                            Feb 7 '12 at 7:00




                                            1




                                            1





                                            Found a fix. It seems that the problem here is the static ProgressDialog. When rotations interrupt the ProgressDialog, it sometimes gets its .dismiss() method called after it is restarted in the new Activity. By making the ProgressDialog created with each Activity, we ensure that this new ProgressDialog isn't killed along with the old Activity. I also made sure that the ProgressDialog is set to null whenever it's dismissed (to aid garbage collection). So we have a solution here! Cheers to those using AsyncTask!

                                            – Scott Biggs
                                            Feb 8 '12 at 6:06





                                            Found a fix. It seems that the problem here is the static ProgressDialog. When rotations interrupt the ProgressDialog, it sometimes gets its .dismiss() method called after it is restarted in the new Activity. By making the ProgressDialog created with each Activity, we ensure that this new ProgressDialog isn't killed along with the old Activity. I also made sure that the ProgressDialog is set to null whenever it's dismissed (to aid garbage collection). So we have a solution here! Cheers to those using AsyncTask!

                                            – Scott Biggs
                                            Feb 8 '12 at 6:06











                                            4














                                            Move the long task to a seperate class. Implement it as a subject-observer pattern. Whenever the activity is created register and while closing unregister with the task class. Task class can use AsyncTask.






                                            share|improve this answer



















                                            • 1





                                              I don't see how that would help. Could you explain in more detail how this prevents the problems I am seeing.

                                              – Heikki Toivonen
                                              Jul 11 '09 at 17:14






                                            • 1





                                              As Haseman said it prevents the backend to access the UI elements and we can seperate the UI from backend, backend runs in seperate thread and it continues to run even after the screen is re-oriented and Register-UnRegister with the Backend task for status updates. The real example I have solved using this is that I have a Download Task, I have moved that to a seperate thread, whenever the thread is created I register-unregister with it.

                                              – Vinay
                                              Jul 14 '09 at 17:17











                                            • Ok, I am revisiting this issue and I don't think I still fully understand this answer. Suppose we have the main activity start an AsyncTask to do a long-running network operation we don't want to interrupt during screen orientation change. I don't see how the new activity can send a message to the AsyncTask started by the old activity. Can you give a code example?

                                              – Heikki Toivonen
                                              May 7 '10 at 7:54













                                            • @Heikki, is my implementation below what you mean?

                                              – beetstra
                                              Apr 29 '11 at 13:58
















                                            4














                                            Move the long task to a seperate class. Implement it as a subject-observer pattern. Whenever the activity is created register and while closing unregister with the task class. Task class can use AsyncTask.






                                            share|improve this answer



















                                            • 1





                                              I don't see how that would help. Could you explain in more detail how this prevents the problems I am seeing.

                                              – Heikki Toivonen
                                              Jul 11 '09 at 17:14






                                            • 1





                                              As Haseman said it prevents the backend to access the UI elements and we can seperate the UI from backend, backend runs in seperate thread and it continues to run even after the screen is re-oriented and Register-UnRegister with the Backend task for status updates. The real example I have solved using this is that I have a Download Task, I have moved that to a seperate thread, whenever the thread is created I register-unregister with it.

                                              – Vinay
                                              Jul 14 '09 at 17:17











                                            • Ok, I am revisiting this issue and I don't think I still fully understand this answer. Suppose we have the main activity start an AsyncTask to do a long-running network operation we don't want to interrupt during screen orientation change. I don't see how the new activity can send a message to the AsyncTask started by the old activity. Can you give a code example?

                                              – Heikki Toivonen
                                              May 7 '10 at 7:54













                                            • @Heikki, is my implementation below what you mean?

                                              – beetstra
                                              Apr 29 '11 at 13:58














                                            4












                                            4








                                            4







                                            Move the long task to a seperate class. Implement it as a subject-observer pattern. Whenever the activity is created register and while closing unregister with the task class. Task class can use AsyncTask.






                                            share|improve this answer













                                            Move the long task to a seperate class. Implement it as a subject-observer pattern. Whenever the activity is created register and while closing unregister with the task class. Task class can use AsyncTask.







                                            share|improve this answer












                                            share|improve this answer



                                            share|improve this answer










                                            answered Jul 11 '09 at 4:56









                                            VinayVinay

                                            3,80672940




                                            3,80672940








                                            • 1





                                              I don't see how that would help. Could you explain in more detail how this prevents the problems I am seeing.

                                              – Heikki Toivonen
                                              Jul 11 '09 at 17:14






                                            • 1





                                              As Haseman said it prevents the backend to access the UI elements and we can seperate the UI from backend, backend runs in seperate thread and it continues to run even after the screen is re-oriented and Register-UnRegister with the Backend task for status updates. The real example I have solved using this is that I have a Download Task, I have moved that to a seperate thread, whenever the thread is created I register-unregister with it.

                                              – Vinay
                                              Jul 14 '09 at 17:17











                                            • Ok, I am revisiting this issue and I don't think I still fully understand this answer. Suppose we have the main activity start an AsyncTask to do a long-running network operation we don't want to interrupt during screen orientation change. I don't see how the new activity can send a message to the AsyncTask started by the old activity. Can you give a code example?

                                              – Heikki Toivonen
                                              May 7 '10 at 7:54













                                            • @Heikki, is my implementation below what you mean?

                                              – beetstra
                                              Apr 29 '11 at 13:58














                                            • 1





                                              I don't see how that would help. Could you explain in more detail how this prevents the problems I am seeing.

                                              – Heikki Toivonen
                                              Jul 11 '09 at 17:14






                                            • 1





                                              As Haseman said it prevents the backend to access the UI elements and we can seperate the UI from backend, backend runs in seperate thread and it continues to run even after the screen is re-oriented and Register-UnRegister with the Backend task for status updates. The real example I have solved using this is that I have a Download Task, I have moved that to a seperate thread, whenever the thread is created I register-unregister with it.

                                              – Vinay
                                              Jul 14 '09 at 17:17











                                            • Ok, I am revisiting this issue and I don't think I still fully understand this answer. Suppose we have the main activity start an AsyncTask to do a long-running network operation we don't want to interrupt during screen orientation change. I don't see how the new activity can send a message to the AsyncTask started by the old activity. Can you give a code example?

                                              – Heikki Toivonen
                                              May 7 '10 at 7:54













                                            • @Heikki, is my implementation below what you mean?

                                              – beetstra
                                              Apr 29 '11 at 13:58








                                            1




                                            1





                                            I don't see how that would help. Could you explain in more detail how this prevents the problems I am seeing.

                                            – Heikki Toivonen
                                            Jul 11 '09 at 17:14





                                            I don't see how that would help. Could you explain in more detail how this prevents the problems I am seeing.

                                            – Heikki Toivonen
                                            Jul 11 '09 at 17:14




                                            1




                                            1





                                            As Haseman said it prevents the backend to access the UI elements and we can seperate the UI from backend, backend runs in seperate thread and it continues to run even after the screen is re-oriented and Register-UnRegister with the Backend task for status updates. The real example I have solved using this is that I have a Download Task, I have moved that to a seperate thread, whenever the thread is created I register-unregister with it.

                                            – Vinay
                                            Jul 14 '09 at 17:17





                                            As Haseman said it prevents the backend to access the UI elements and we can seperate the UI from backend, backend runs in seperate thread and it continues to run even after the screen is re-oriented and Register-UnRegister with the Backend task for status updates. The real example I have solved using this is that I have a Download Task, I have moved that to a seperate thread, whenever the thread is created I register-unregister with it.

                                            – Vinay
                                            Jul 14 '09 at 17:17













                                            Ok, I am revisiting this issue and I don't think I still fully understand this answer. Suppose we have the main activity start an AsyncTask to do a long-running network operation we don't want to interrupt during screen orientation change. I don't see how the new activity can send a message to the AsyncTask started by the old activity. Can you give a code example?

                                            – Heikki Toivonen
                                            May 7 '10 at 7:54







                                            Ok, I am revisiting this issue and I don't think I still fully understand this answer. Suppose we have the main activity start an AsyncTask to do a long-running network operation we don't want to interrupt during screen orientation change. I don't see how the new activity can send a message to the AsyncTask started by the old activity. Can you give a code example?

                                            – Heikki Toivonen
                                            May 7 '10 at 7:54















                                            @Heikki, is my implementation below what you mean?

                                            – beetstra
                                            Apr 29 '11 at 13:58





                                            @Heikki, is my implementation below what you mean?

                                            – beetstra
                                            Apr 29 '11 at 13:58











                                            4














                                            The trick is to show/dismiss the dialog within AsyncTask during onPreExecute/onPostExecute as usual, though in case of orientation-change create/show a new instance of the dialog in the activity and pass its reference to the task.



                                            public class MainActivity extends Activity {
                                            private Button mButton;
                                            private MyTask mTask = null;

                                            @Override
                                            public void onCreate(Bundle savedInstanceState) {
                                            super.onCreate(savedInstanceState);
                                            setContentView(R.layout.main);

                                            MyTask task = (MyTask) getLastNonConfigurationInstance();
                                            if(task != null){
                                            mTask = task;
                                            mTask.mContext = this;
                                            mTask.mDialog = ProgressDialog.show(this, "", "", true);
                                            }

                                            mButton = (Button) findViewById(R.id.button1);
                                            mButton.setOnClickListener(new View.OnClickListener(){
                                            public void onClick(View v){
                                            mTask = new MyTask(MainActivity.this);
                                            mTask.execute();
                                            }
                                            });
                                            }


                                            @Override
                                            public Object onRetainNonConfigurationInstance() {
                                            String str = "null";
                                            if(mTask != null){
                                            str = mTask.toString();
                                            mTask.mDialog.dismiss();
                                            }
                                            Toast.makeText(this, str, Toast.LENGTH_SHORT).show();
                                            return mTask;
                                            }



                                            private class MyTask extends AsyncTask<Void, Void, Void>{
                                            private ProgressDialog mDialog;
                                            private MainActivity mContext;


                                            public MyTask(MainActivity context){
                                            super();
                                            mContext = context;
                                            }


                                            protected void onPreExecute() {
                                            mDialog = ProgressDialog.show(MainActivity.this, "", "", true);
                                            }

                                            protected void onPostExecute(Void result) {
                                            mContext.mTask = null;
                                            mDialog.dismiss();
                                            }


                                            @Override
                                            protected Void doInBackground(Void... params) {
                                            SystemClock.sleep(5000);
                                            return null;
                                            }
                                            }
                                            }





                                            share|improve this answer






























                                              4














                                              The trick is to show/dismiss the dialog within AsyncTask during onPreExecute/onPostExecute as usual, though in case of orientation-change create/show a new instance of the dialog in the activity and pass its reference to the task.



                                              public class MainActivity extends Activity {
                                              private Button mButton;
                                              private MyTask mTask = null;

                                              @Override
                                              public void onCreate(Bundle savedInstanceState) {
                                              super.onCreate(savedInstanceState);
                                              setContentView(R.layout.main);

                                              MyTask task = (MyTask) getLastNonConfigurationInstance();
                                              if(task != null){
                                              mTask = task;
                                              mTask.mContext = this;
                                              mTask.mDialog = ProgressDialog.show(this, "", "", true);
                                              }

                                              mButton = (Button) findViewById(R.id.button1);
                                              mButton.setOnClickListener(new View.OnClickListener(){
                                              public void onClick(View v){
                                              mTask = new MyTask(MainActivity.this);
                                              mTask.execute();
                                              }
                                              });
                                              }


                                              @Override
                                              public Object onRetainNonConfigurationInstance() {
                                              String str = "null";
                                              if(mTask != null){
                                              str = mTask.toString();
                                              mTask.mDialog.dismiss();
                                              }
                                              Toast.makeText(this, str, Toast.LENGTH_SHORT).show();
                                              return mTask;
                                              }



                                              private class MyTask extends AsyncTask<Void, Void, Void>{
                                              private ProgressDialog mDialog;
                                              private MainActivity mContext;


                                              public MyTask(MainActivity context){
                                              super();
                                              mContext = context;
                                              }


                                              protected void onPreExecute() {
                                              mDialog = ProgressDialog.show(MainActivity.this, "", "", true);
                                              }

                                              protected void onPostExecute(Void result) {
                                              mContext.mTask = null;
                                              mDialog.dismiss();
                                              }


                                              @Override
                                              protected Void doInBackground(Void... params) {
                                              SystemClock.sleep(5000);
                                              return null;
                                              }
                                              }
                                              }





                                              share|improve this answer




























                                                4












                                                4








                                                4







                                                The trick is to show/dismiss the dialog within AsyncTask during onPreExecute/onPostExecute as usual, though in case of orientation-change create/show a new instance of the dialog in the activity and pass its reference to the task.



                                                public class MainActivity extends Activity {
                                                private Button mButton;
                                                private MyTask mTask = null;

                                                @Override
                                                public void onCreate(Bundle savedInstanceState) {
                                                super.onCreate(savedInstanceState);
                                                setContentView(R.layout.main);

                                                MyTask task = (MyTask) getLastNonConfigurationInstance();
                                                if(task != null){
                                                mTask = task;
                                                mTask.mContext = this;
                                                mTask.mDialog = ProgressDialog.show(this, "", "", true);
                                                }

                                                mButton = (Button) findViewById(R.id.button1);
                                                mButton.setOnClickListener(new View.OnClickListener(){
                                                public void onClick(View v){
                                                mTask = new MyTask(MainActivity.this);
                                                mTask.execute();
                                                }
                                                });
                                                }


                                                @Override
                                                public Object onRetainNonConfigurationInstance() {
                                                String str = "null";
                                                if(mTask != null){
                                                str = mTask.toString();
                                                mTask.mDialog.dismiss();
                                                }
                                                Toast.makeText(this, str, Toast.LENGTH_SHORT).show();
                                                return mTask;
                                                }



                                                private class MyTask extends AsyncTask<Void, Void, Void>{
                                                private ProgressDialog mDialog;
                                                private MainActivity mContext;


                                                public MyTask(MainActivity context){
                                                super();
                                                mContext = context;
                                                }


                                                protected void onPreExecute() {
                                                mDialog = ProgressDialog.show(MainActivity.this, "", "", true);
                                                }

                                                protected void onPostExecute(Void result) {
                                                mContext.mTask = null;
                                                mDialog.dismiss();
                                                }


                                                @Override
                                                protected Void doInBackground(Void... params) {
                                                SystemClock.sleep(5000);
                                                return null;
                                                }
                                                }
                                                }





                                                share|improve this answer















                                                The trick is to show/dismiss the dialog within AsyncTask during onPreExecute/onPostExecute as usual, though in case of orientation-change create/show a new instance of the dialog in the activity and pass its reference to the task.



                                                public class MainActivity extends Activity {
                                                private Button mButton;
                                                private MyTask mTask = null;

                                                @Override
                                                public void onCreate(Bundle savedInstanceState) {
                                                super.onCreate(savedInstanceState);
                                                setContentView(R.layout.main);

                                                MyTask task = (MyTask) getLastNonConfigurationInstance();
                                                if(task != null){
                                                mTask = task;
                                                mTask.mContext = this;
                                                mTask.mDialog = ProgressDialog.show(this, "", "", true);
                                                }

                                                mButton = (Button) findViewById(R.id.button1);
                                                mButton.setOnClickListener(new View.OnClickListener(){
                                                public void onClick(View v){
                                                mTask = new MyTask(MainActivity.this);
                                                mTask.execute();
                                                }
                                                });
                                                }


                                                @Override
                                                public Object onRetainNonConfigurationInstance() {
                                                String str = "null";
                                                if(mTask != null){
                                                str = mTask.toString();
                                                mTask.mDialog.dismiss();
                                                }
                                                Toast.makeText(this, str, Toast.LENGTH_SHORT).show();
                                                return mTask;
                                                }



                                                private class MyTask extends AsyncTask<Void, Void, Void>{
                                                private ProgressDialog mDialog;
                                                private MainActivity mContext;


                                                public MyTask(MainActivity context){
                                                super();
                                                mContext = context;
                                                }


                                                protected void onPreExecute() {
                                                mDialog = ProgressDialog.show(MainActivity.this, "", "", true);
                                                }

                                                protected void onPostExecute(Void result) {
                                                mContext.mTask = null;
                                                mDialog.dismiss();
                                                }


                                                @Override
                                                protected Void doInBackground(Void... params) {
                                                SystemClock.sleep(5000);
                                                return null;
                                                }
                                                }
                                                }






                                                share|improve this answer














                                                share|improve this answer



                                                share|improve this answer








                                                edited Jun 28 '11 at 13:20

























                                                answered Jun 27 '11 at 14:11









                                                n224576n224576

                                                1,486193




                                                1,486193























                                                    4














                                                    I have done it like this:



                                                        package com.palewar;
                                                    import android.app.Activity;
                                                    import android.app.ProgressDialog;
                                                    import android.os.Bundle;
                                                    import android.os.Handler;
                                                    import android.os.Message;

                                                    public class ThreadActivity extends Activity {


                                                    static ProgressDialog dialog;
                                                    private Thread downloadThread;
                                                    final static Handler handler = new Handler() {

                                                    @Override
                                                    public void handleMessage(Message msg) {

                                                    super.handleMessage(msg);

                                                    dialog.dismiss();

                                                    }

                                                    };

                                                    protected void onDestroy() {
                                                    super.onDestroy();
                                                    if (dialog != null && dialog.isShowing()) {
                                                    dialog.dismiss();
                                                    dialog = null;
                                                    }

                                                    }

                                                    /** Called when the activity is first created. */
                                                    @Override
                                                    public void onCreate(Bundle savedInstanceState) {
                                                    super.onCreate(savedInstanceState);
                                                    setContentView(R.layout.main);

                                                    downloadThread = (Thread) getLastNonConfigurationInstance();
                                                    if (downloadThread != null && downloadThread.isAlive()) {
                                                    dialog = ProgressDialog.show(ThreadActivity.this, "",
                                                    "Signing in...", false);
                                                    }

                                                    dialog = ProgressDialog.show(ThreadActivity.this, "",
                                                    "Signing in ...", false);

                                                    downloadThread = new MyThread();
                                                    downloadThread.start();
                                                    // processThread();
                                                    }

                                                    // Save the thread
                                                    @Override
                                                    public Object onRetainNonConfigurationInstance() {
                                                    return downloadThread;
                                                    }


                                                    static public class MyThread extends Thread {
                                                    @Override
                                                    public void run() {

                                                    try {
                                                    // Simulate a slow network
                                                    try {
                                                    new Thread().sleep(5000);
                                                    } catch (InterruptedException e) {
                                                    e.printStackTrace();
                                                    }
                                                    handler.sendEmptyMessage(0);

                                                    } finally {

                                                    }
                                                    }
                                                    }

                                                    }


                                                    You can also try and let me know it works for you or not






                                                    share|improve this answer


























                                                    • The onDestroy code may not be executed at all, from Developer's page: "Note the "Killable" column in the above table -- for those methods that are marked as being killable, after that method returns the process hosting the activity may killed by the system at any time without another line of its code being executed"

                                                      – ilomambo
                                                      May 5 '12 at 8:21













                                                    • I firmly believe that "onRetainNonConfigurationInstance()" is the method to be used for such cases...nyc work

                                                      – Nitin Bansal
                                                      Aug 21 '12 at 4:04











                                                    • I am facing similar problem, as Sachin Gurnani does I using static declaration to fix my problem. stackoverflow.com/questions/12058774/…

                                                      – Steven Du
                                                      Aug 22 '12 at 1:32


















                                                    4














                                                    I have done it like this:



                                                        package com.palewar;
                                                    import android.app.Activity;
                                                    import android.app.ProgressDialog;
                                                    import android.os.Bundle;
                                                    import android.os.Handler;
                                                    import android.os.Message;

                                                    public class ThreadActivity extends Activity {


                                                    static ProgressDialog dialog;
                                                    private Thread downloadThread;
                                                    final static Handler handler = new Handler() {

                                                    @Override
                                                    public void handleMessage(Message msg) {

                                                    super.handleMessage(msg);

                                                    dialog.dismiss();

                                                    }

                                                    };

                                                    protected void onDestroy() {
                                                    super.onDestroy();
                                                    if (dialog != null && dialog.isShowing()) {
                                                    dialog.dismiss();
                                                    dialog = null;
                                                    }

                                                    }

                                                    /** Called when the activity is first created. */
                                                    @Override
                                                    public void onCreate(Bundle savedInstanceState) {
                                                    super.onCreate(savedInstanceState);
                                                    setContentView(R.layout.main);

                                                    downloadThread = (Thread) getLastNonConfigurationInstance();
                                                    if (downloadThread != null && downloadThread.isAlive()) {
                                                    dialog = ProgressDialog.show(ThreadActivity.this, "",
                                                    "Signing in...", false);
                                                    }

                                                    dialog = ProgressDialog.show(ThreadActivity.this, "",
                                                    "Signing in ...", false);

                                                    downloadThread = new MyThread();
                                                    downloadThread.start();
                                                    // processThread();
                                                    }

                                                    // Save the thread
                                                    @Override
                                                    public Object onRetainNonConfigurationInstance() {
                                                    return downloadThread;
                                                    }


                                                    static public class MyThread extends Thread {
                                                    @Override
                                                    public void run() {

                                                    try {
                                                    // Simulate a slow network
                                                    try {
                                                    new Thread().sleep(5000);
                                                    } catch (InterruptedException e) {
                                                    e.printStackTrace();
                                                    }
                                                    handler.sendEmptyMessage(0);

                                                    } finally {

                                                    }
                                                    }
                                                    }

                                                    }


                                                    You can also try and let me know it works for you or not






                                                    share|improve this answer


























                                                    • The onDestroy code may not be executed at all, from Developer's page: "Note the "Killable" column in the above table -- for those methods that are marked as being killable, after that method returns the process hosting the activity may killed by the system at any time without another line of its code being executed"

                                                      – ilomambo
                                                      May 5 '12 at 8:21













                                                    • I firmly believe that "onRetainNonConfigurationInstance()" is the method to be used for such cases...nyc work

                                                      – Nitin Bansal
                                                      Aug 21 '12 at 4:04











                                                    • I am facing similar problem, as Sachin Gurnani does I using static declaration to fix my problem. stackoverflow.com/questions/12058774/…

                                                      – Steven Du
                                                      Aug 22 '12 at 1:32
















                                                    4












                                                    4








                                                    4







                                                    I have done it like this:



                                                        package com.palewar;
                                                    import android.app.Activity;
                                                    import android.app.ProgressDialog;
                                                    import android.os.Bundle;
                                                    import android.os.Handler;
                                                    import android.os.Message;

                                                    public class ThreadActivity extends Activity {


                                                    static ProgressDialog dialog;
                                                    private Thread downloadThread;
                                                    final static Handler handler = new Handler() {

                                                    @Override
                                                    public void handleMessage(Message msg) {

                                                    super.handleMessage(msg);

                                                    dialog.dismiss();

                                                    }

                                                    };

                                                    protected void onDestroy() {
                                                    super.onDestroy();
                                                    if (dialog != null && dialog.isShowing()) {
                                                    dialog.dismiss();
                                                    dialog = null;
                                                    }

                                                    }

                                                    /** Called when the activity is first created. */
                                                    @Override
                                                    public void onCreate(Bundle savedInstanceState) {
                                                    super.onCreate(savedInstanceState);
                                                    setContentView(R.layout.main);

                                                    downloadThread = (Thread) getLastNonConfigurationInstance();
                                                    if (downloadThread != null && downloadThread.isAlive()) {
                                                    dialog = ProgressDialog.show(ThreadActivity.this, "",
                                                    "Signing in...", false);
                                                    }

                                                    dialog = ProgressDialog.show(ThreadActivity.this, "",
                                                    "Signing in ...", false);

                                                    downloadThread = new MyThread();
                                                    downloadThread.start();
                                                    // processThread();
                                                    }

                                                    // Save the thread
                                                    @Override
                                                    public Object onRetainNonConfigurationInstance() {
                                                    return downloadThread;
                                                    }


                                                    static public class MyThread extends Thread {
                                                    @Override
                                                    public void run() {

                                                    try {
                                                    // Simulate a slow network
                                                    try {
                                                    new Thread().sleep(5000);
                                                    } catch (InterruptedException e) {
                                                    e.printStackTrace();
                                                    }
                                                    handler.sendEmptyMessage(0);

                                                    } finally {

                                                    }
                                                    }
                                                    }

                                                    }


                                                    You can also try and let me know it works for you or not






                                                    share|improve this answer















                                                    I have done it like this:



                                                        package com.palewar;
                                                    import android.app.Activity;
                                                    import android.app.ProgressDialog;
                                                    import android.os.Bundle;
                                                    import android.os.Handler;
                                                    import android.os.Message;

                                                    public class ThreadActivity extends Activity {


                                                    static ProgressDialog dialog;
                                                    private Thread downloadThread;
                                                    final static Handler handler = new Handler() {

                                                    @Override
                                                    public void handleMessage(Message msg) {

                                                    super.handleMessage(msg);

                                                    dialog.dismiss();

                                                    }

                                                    };

                                                    protected void onDestroy() {
                                                    super.onDestroy();
                                                    if (dialog != null && dialog.isShowing()) {
                                                    dialog.dismiss();
                                                    dialog = null;
                                                    }

                                                    }

                                                    /** Called when the activity is first created. */
                                                    @Override
                                                    public void onCreate(Bundle savedInstanceState) {
                                                    super.onCreate(savedInstanceState);
                                                    setContentView(R.layout.main);

                                                    downloadThread = (Thread) getLastNonConfigurationInstance();
                                                    if (downloadThread != null && downloadThread.isAlive()) {
                                                    dialog = ProgressDialog.show(ThreadActivity.this, "",
                                                    "Signing in...", false);
                                                    }

                                                    dialog = ProgressDialog.show(ThreadActivity.this, "",
                                                    "Signing in ...", false);

                                                    downloadThread = new MyThread();
                                                    downloadThread.start();
                                                    // processThread();
                                                    }

                                                    // Save the thread
                                                    @Override
                                                    public Object onRetainNonConfigurationInstance() {
                                                    return downloadThread;
                                                    }


                                                    static public class MyThread extends Thread {
                                                    @Override
                                                    public void run() {

                                                    try {
                                                    // Simulate a slow network
                                                    try {
                                                    new Thread().sleep(5000);
                                                    } catch (InterruptedException e) {
                                                    e.printStackTrace();
                                                    }
                                                    handler.sendEmptyMessage(0);

                                                    } finally {

                                                    }
                                                    }
                                                    }

                                                    }


                                                    You can also try and let me know it works for you or not







                                                    share|improve this answer














                                                    share|improve this answer



                                                    share|improve this answer








                                                    edited Jun 29 '13 at 5:03









                                                    7bluephoenix

                                                    908617




                                                    908617










                                                    answered Mar 24 '12 at 13:13









                                                    Sachin GurnaniSachin Gurnani

                                                    3,68383647




                                                    3,68383647













                                                    • The onDestroy code may not be executed at all, from Developer's page: "Note the "Killable" column in the above table -- for those methods that are marked as being killable, after that method returns the process hosting the activity may killed by the system at any time without another line of its code being executed"

                                                      – ilomambo
                                                      May 5 '12 at 8:21













                                                    • I firmly believe that "onRetainNonConfigurationInstance()" is the method to be used for such cases...nyc work

                                                      – Nitin Bansal
                                                      Aug 21 '12 at 4:04











                                                    • I am facing similar problem, as Sachin Gurnani does I using static declaration to fix my problem. stackoverflow.com/questions/12058774/…

                                                      – Steven Du
                                                      Aug 22 '12 at 1:32





















                                                    • The onDestroy code may not be executed at all, from Developer's page: "Note the "Killable" column in the above table -- for those methods that are marked as being killable, after that method returns the process hosting the activity may killed by the system at any time without another line of its code being executed"

                                                      – ilomambo
                                                      May 5 '12 at 8:21













                                                    • I firmly believe that "onRetainNonConfigurationInstance()" is the method to be used for such cases...nyc work

                                                      – Nitin Bansal
                                                      Aug 21 '12 at 4:04











                                                    • I am facing similar problem, as Sachin Gurnani does I using static declaration to fix my problem. stackoverflow.com/questions/12058774/…

                                                      – Steven Du
                                                      Aug 22 '12 at 1:32



















                                                    The onDestroy code may not be executed at all, from Developer's page: "Note the "Killable" column in the above table -- for those methods that are marked as being killable, after that method returns the process hosting the activity may killed by the system at any time without another line of its code being executed"

                                                    – ilomambo
                                                    May 5 '12 at 8:21







                                                    The onDestroy code may not be executed at all, from Developer's page: "Note the "Killable" column in the above table -- for those methods that are marked as being killable, after that method returns the process hosting the activity may killed by the system at any time without another line of its code being executed"

                                                    – ilomambo
                                                    May 5 '12 at 8:21















                                                    I firmly believe that "onRetainNonConfigurationInstance()" is the method to be used for such cases...nyc work

                                                    – Nitin Bansal
                                                    Aug 21 '12 at 4:04





                                                    I firmly believe that "onRetainNonConfigurationInstance()" is the method to be used for such cases...nyc work

                                                    – Nitin Bansal
                                                    Aug 21 '12 at 4:04













                                                    I am facing similar problem, as Sachin Gurnani does I using static declaration to fix my problem. stackoverflow.com/questions/12058774/…

                                                    – Steven Du
                                                    Aug 22 '12 at 1:32







                                                    I am facing similar problem, as Sachin Gurnani does I using static declaration to fix my problem. stackoverflow.com/questions/12058774/…

                                                    – Steven Du
                                                    Aug 22 '12 at 1:32













                                                    2














                                                    If you create a background Service that does all the heavy lifting (tcp requests/response, unmarshalling), the View and Activity can be destroyed and re-created without leaking window or losing data. This allows the Android recommended behavior, which is to destroy an Activity on each configuration change (eg. for each orientation change).



                                                    It is a bit more complex, but it is the best way for invoking server request, data pre/post-processing, etc.



                                                    You may even use your Service to queue each request to a server, so it makes it easy and efficient to handle those things.



                                                    The dev guide has a full chapter on Services.






                                                    share|improve this answer


























                                                    • A Service is more work than an AsyncTask but can be a better approach in some situations. It is not necessarily better, is it? That being said, I don't understand how this solves the problem of the ProgressDialog that is leaked from the main Activity. Where do you instanciate the ProgressDialog? Where do you dismiss it?

                                                      – rds
                                                      Mar 10 '11 at 18:12
















                                                    2














                                                    If you create a background Service that does all the heavy lifting (tcp requests/response, unmarshalling), the View and Activity can be destroyed and re-created without leaking window or losing data. This allows the Android recommended behavior, which is to destroy an Activity on each configuration change (eg. for each orientation change).



                                                    It is a bit more complex, but it is the best way for invoking server request, data pre/post-processing, etc.



                                                    You may even use your Service to queue each request to a server, so it makes it easy and efficient to handle those things.



                                                    The dev guide has a full chapter on Services.






                                                    share|improve this answer


























                                                    • A Service is more work than an AsyncTask but can be a better approach in some situations. It is not necessarily better, is it? That being said, I don't understand how this solves the problem of the ProgressDialog that is leaked from the main Activity. Where do you instanciate the ProgressDialog? Where do you dismiss it?

                                                      – rds
                                                      Mar 10 '11 at 18:12














                                                    2












                                                    2








                                                    2







                                                    If you create a background Service that does all the heavy lifting (tcp requests/response, unmarshalling), the View and Activity can be destroyed and re-created without leaking window or losing data. This allows the Android recommended behavior, which is to destroy an Activity on each configuration change (eg. for each orientation change).



                                                    It is a bit more complex, but it is the best way for invoking server request, data pre/post-processing, etc.



                                                    You may even use your Service to queue each request to a server, so it makes it easy and efficient to handle those things.



                                                    The dev guide has a full chapter on Services.






                                                    share|improve this answer















                                                    If you create a background Service that does all the heavy lifting (tcp requests/response, unmarshalling), the View and Activity can be destroyed and re-created without leaking window or losing data. This allows the Android recommended behavior, which is to destroy an Activity on each configuration change (eg. for each orientation change).



                                                    It is a bit more complex, but it is the best way for invoking server request, data pre/post-processing, etc.



                                                    You may even use your Service to queue each request to a server, so it makes it easy and efficient to handle those things.



                                                    The dev guide has a full chapter on Services.







                                                    share|improve this answer














                                                    share|improve this answer



                                                    share|improve this answer








                                                    edited Mar 10 '11 at 17:11









                                                    rds

                                                    18.1k1080113




                                                    18.1k1080113










                                                    answered Dec 26 '10 at 5:37









                                                    acardenas89acardenas89

                                                    211




                                                    211













                                                    • A Service is more work than an AsyncTask but can be a better approach in some situations. It is not necessarily better, is it? That being said, I don't understand how this solves the problem of the ProgressDialog that is leaked from the main Activity. Where do you instanciate the ProgressDialog? Where do you dismiss it?

                                                      – rds
                                                      Mar 10 '11 at 18:12



















                                                    • A Service is more work than an AsyncTask but can be a better approach in some situations. It is not necessarily better, is it? That being said, I don't understand how this solves the problem of the ProgressDialog that is leaked from the main Activity. Where do you instanciate the ProgressDialog? Where do you dismiss it?

                                                      – rds
                                                      Mar 10 '11 at 18:12

















                                                    A Service is more work than an AsyncTask but can be a better approach in some situations. It is not necessarily better, is it? That being said, I don't understand how this solves the problem of the ProgressDialog that is leaked from the main Activity. Where do you instanciate the ProgressDialog? Where do you dismiss it?

                                                    – rds
                                                    Mar 10 '11 at 18:12





                                                    A Service is more work than an AsyncTask but can be a better approach in some situations. It is not necessarily better, is it? That being said, I don't understand how this solves the problem of the ProgressDialog that is leaked from the main Activity. Where do you instanciate the ProgressDialog? Where do you dismiss it?

                                                    – rds
                                                    Mar 10 '11 at 18:12











                                                    2














                                                    I have an implementation which allows the activity to be destroyed on a screen orientation change, but still destroys the dialog in the recreated activity successfully.
                                                    I use ...NonConfigurationInstance to attach the background task to the recreated activity.
                                                    The normal Android framework handles recreating the dialog itself, nothing is changed there.



                                                    I subclassed AsyncTask adding a field for the 'owning' activity, and a method to update this owner.



                                                    class MyBackgroundTask extends AsyncTask<...> {
                                                    MyBackgroundTask (Activity a, ...) {
                                                    super();
                                                    this.ownerActivity = a;
                                                    }

                                                    public void attach(Activity a) {
                                                    ownerActivity = a;
                                                    }

                                                    protected void onPostExecute(Integer result) {
                                                    super.onPostExecute(result);
                                                    ownerActivity.dismissDialog(DIALOG_PROGRESS);
                                                    }

                                                    ...
                                                    }


                                                    In my activity class I added a field backgroundTask referring to the 'owned' backgroundtask, and I update this field using onRetainNonConfigurationInstance and getLastNonConfigurationInstance.



                                                    class MyActivity extends Activity {
                                                    public void onCreate(Bundle savedInstanceState) {
                                                    ...
                                                    if (getLastNonConfigurationInstance() != null) {
                                                    backgroundTask = (MyBackgroundTask) getLastNonConfigurationInstance();
                                                    backgroundTask.attach(this);
                                                    }
                                                    }

                                                    void startBackgroundTask() {
                                                    backgroundTask = new MyBackgroundTask(this, ...);
                                                    showDialog(DIALOG_PROGRESS);
                                                    backgroundTask.execute(...);
                                                    }

                                                    public Object onRetainNonConfigurationInstance() {
                                                    if (backgroundTask != null && backgroundTask.getStatus() != Status.FINISHED)
                                                    return backgroundTask;
                                                    return null;
                                                    }
                                                    ...
                                                    }


                                                    Suggestions for further improvement:




                                                    • Clear the backgroundTask reference in the activity after the task is finished to release any memory or other resources associated with it.

                                                    • Clear the ownerActivity reference in the backgroundtask before the activity is destroyed in case it will not be recreated immediately.

                                                    • Create a BackgroundTask interface and/or collection to allow different types of tasks to run from the same owning activity.






                                                    share|improve this answer




























                                                      2














                                                      I have an implementation which allows the activity to be destroyed on a screen orientation change, but still destroys the dialog in the recreated activity successfully.
                                                      I use ...NonConfigurationInstance to attach the background task to the recreated activity.
                                                      The normal Android framework handles recreating the dialog itself, nothing is changed there.



                                                      I subclassed AsyncTask adding a field for the 'owning' activity, and a method to update this owner.



                                                      class MyBackgroundTask extends AsyncTask<...> {
                                                      MyBackgroundTask (Activity a, ...) {
                                                      super();
                                                      this.ownerActivity = a;
                                                      }

                                                      public void attach(Activity a) {
                                                      ownerActivity = a;
                                                      }

                                                      protected void onPostExecute(Integer result) {
                                                      super.onPostExecute(result);
                                                      ownerActivity.dismissDialog(DIALOG_PROGRESS);
                                                      }

                                                      ...
                                                      }


                                                      In my activity class I added a field backgroundTask referring to the 'owned' backgroundtask, and I update this field using onRetainNonConfigurationInstance and getLastNonConfigurationInstance.



                                                      class MyActivity extends Activity {
                                                      public void onCreate(Bundle savedInstanceState) {
                                                      ...
                                                      if (getLastNonConfigurationInstance() != null) {
                                                      backgroundTask = (MyBackgroundTask) getLastNonConfigurationInstance();
                                                      backgroundTask.attach(this);
                                                      }
                                                      }

                                                      void startBackgroundTask() {
                                                      backgroundTask = new MyBackgroundTask(this, ...);
                                                      showDialog(DIALOG_PROGRESS);
                                                      backgroundTask.execute(...);
                                                      }

                                                      public Object onRetainNonConfigurationInstance() {
                                                      if (backgroundTask != null && backgroundTask.getStatus() != Status.FINISHED)
                                                      return backgroundTask;
                                                      return null;
                                                      }
                                                      ...
                                                      }


                                                      Suggestions for further improvement:




                                                      • Clear the backgroundTask reference in the activity after the task is finished to release any memory or other resources associated with it.

                                                      • Clear the ownerActivity reference in the backgroundtask before the activity is destroyed in case it will not be recreated immediately.

                                                      • Create a BackgroundTask interface and/or collection to allow different types of tasks to run from the same owning activity.






                                                      share|improve this answer


























                                                        2












                                                        2








                                                        2







                                                        I have an implementation which allows the activity to be destroyed on a screen orientation change, but still destroys the dialog in the recreated activity successfully.
                                                        I use ...NonConfigurationInstance to attach the background task to the recreated activity.
                                                        The normal Android framework handles recreating the dialog itself, nothing is changed there.



                                                        I subclassed AsyncTask adding a field for the 'owning' activity, and a method to update this owner.



                                                        class MyBackgroundTask extends AsyncTask<...> {
                                                        MyBackgroundTask (Activity a, ...) {
                                                        super();
                                                        this.ownerActivity = a;
                                                        }

                                                        public void attach(Activity a) {
                                                        ownerActivity = a;
                                                        }

                                                        protected void onPostExecute(Integer result) {
                                                        super.onPostExecute(result);
                                                        ownerActivity.dismissDialog(DIALOG_PROGRESS);
                                                        }

                                                        ...
                                                        }


                                                        In my activity class I added a field backgroundTask referring to the 'owned' backgroundtask, and I update this field using onRetainNonConfigurationInstance and getLastNonConfigurationInstance.



                                                        class MyActivity extends Activity {
                                                        public void onCreate(Bundle savedInstanceState) {
                                                        ...
                                                        if (getLastNonConfigurationInstance() != null) {
                                                        backgroundTask = (MyBackgroundTask) getLastNonConfigurationInstance();
                                                        backgroundTask.attach(this);
                                                        }
                                                        }

                                                        void startBackgroundTask() {
                                                        backgroundTask = new MyBackgroundTask(this, ...);
                                                        showDialog(DIALOG_PROGRESS);
                                                        backgroundTask.execute(...);
                                                        }

                                                        public Object onRetainNonConfigurationInstance() {
                                                        if (backgroundTask != null && backgroundTask.getStatus() != Status.FINISHED)
                                                        return backgroundTask;
                                                        return null;
                                                        }
                                                        ...
                                                        }


                                                        Suggestions for further improvement:




                                                        • Clear the backgroundTask reference in the activity after the task is finished to release any memory or other resources associated with it.

                                                        • Clear the ownerActivity reference in the backgroundtask before the activity is destroyed in case it will not be recreated immediately.

                                                        • Create a BackgroundTask interface and/or collection to allow different types of tasks to run from the same owning activity.






                                                        share|improve this answer













                                                        I have an implementation which allows the activity to be destroyed on a screen orientation change, but still destroys the dialog in the recreated activity successfully.
                                                        I use ...NonConfigurationInstance to attach the background task to the recreated activity.
                                                        The normal Android framework handles recreating the dialog itself, nothing is changed there.



                                                        I subclassed AsyncTask adding a field for the 'owning' activity, and a method to update this owner.



                                                        class MyBackgroundTask extends AsyncTask<...> {
                                                        MyBackgroundTask (Activity a, ...) {
                                                        super();
                                                        this.ownerActivity = a;
                                                        }

                                                        public void attach(Activity a) {
                                                        ownerActivity = a;
                                                        }

                                                        protected void onPostExecute(Integer result) {
                                                        super.onPostExecute(result);
                                                        ownerActivity.dismissDialog(DIALOG_PROGRESS);
                                                        }

                                                        ...
                                                        }


                                                        In my activity class I added a field backgroundTask referring to the 'owned' backgroundtask, and I update this field using onRetainNonConfigurationInstance and getLastNonConfigurationInstance.



                                                        class MyActivity extends Activity {
                                                        public void onCreate(Bundle savedInstanceState) {
                                                        ...
                                                        if (getLastNonConfigurationInstance() != null) {
                                                        backgroundTask = (MyBackgroundTask) getLastNonConfigurationInstance();
                                                        backgroundTask.attach(this);
                                                        }
                                                        }

                                                        void startBackgroundTask() {
                                                        backgroundTask = new MyBackgroundTask(this, ...);
                                                        showDialog(DIALOG_PROGRESS);
                                                        backgroundTask.execute(...);
                                                        }

                                                        public Object onRetainNonConfigurationInstance() {
                                                        if (backgroundTask != null && backgroundTask.getStatus() != Status.FINISHED)
                                                        return backgroundTask;
                                                        return null;
                                                        }
                                                        ...
                                                        }


                                                        Suggestions for further improvement:




                                                        • Clear the backgroundTask reference in the activity after the task is finished to release any memory or other resources associated with it.

                                                        • Clear the ownerActivity reference in the backgroundtask before the activity is destroyed in case it will not be recreated immediately.

                                                        • Create a BackgroundTask interface and/or collection to allow different types of tasks to run from the same owning activity.







                                                        share|improve this answer












                                                        share|improve this answer



                                                        share|improve this answer










                                                        answered Apr 29 '11 at 13:56









                                                        beetstrabeetstra

                                                        5,82243343




                                                        5,82243343























                                                            2














                                                            If you maintain two layouts, all UI thread should be terminated.



                                                            If you use AsynTask, then you can easily call .cancel() method inside onDestroy() method of current activity.



                                                            @Override
                                                            protected void onDestroy (){
                                                            removeDialog(DIALOG_LOGIN_ID); // remove loading dialog
                                                            if (loginTask != null){
                                                            if (loginTask.getStatus() != AsyncTask.Status.FINISHED)
                                                            loginTask.cancel(true); //cancel AsyncTask
                                                            }
                                                            super.onDestroy();
                                                            }


                                                            For AsyncTask, read more in "Cancelling a task" section at here.



                                                            Update:
                                                            Added condition to check status, as it can be only cancelled if it is in running state.
                                                            Also note that the AsyncTask can only be executed one time.






                                                            share|improve this answer






























                                                              2














                                                              If you maintain two layouts, all UI thread should be terminated.



                                                              If you use AsynTask, then you can easily call .cancel() method inside onDestroy() method of current activity.



                                                              @Override
                                                              protected void onDestroy (){
                                                              removeDialog(DIALOG_LOGIN_ID); // remove loading dialog
                                                              if (loginTask != null){
                                                              if (loginTask.getStatus() != AsyncTask.Status.FINISHED)
                                                              loginTask.cancel(true); //cancel AsyncTask
                                                              }
                                                              super.onDestroy();
                                                              }


                                                              For AsyncTask, read more in "Cancelling a task" section at here.



                                                              Update:
                                                              Added condition to check status, as it can be only cancelled if it is in running state.
                                                              Also note that the AsyncTask can only be executed one time.






                                                              share|improve this answer




























                                                                2












                                                                2








                                                                2







                                                                If you maintain two layouts, all UI thread should be terminated.



                                                                If you use AsynTask, then you can easily call .cancel() method inside onDestroy() method of current activity.



                                                                @Override
                                                                protected void onDestroy (){
                                                                removeDialog(DIALOG_LOGIN_ID); // remove loading dialog
                                                                if (loginTask != null){
                                                                if (loginTask.getStatus() != AsyncTask.Status.FINISHED)
                                                                loginTask.cancel(true); //cancel AsyncTask
                                                                }
                                                                super.onDestroy();
                                                                }


                                                                For AsyncTask, read more in "Cancelling a task" section at here.



                                                                Update:
                                                                Added condition to check status, as it can be only cancelled if it is in running state.
                                                                Also note that the AsyncTask can only be executed one time.






                                                                share|improve this answer















                                                                If you maintain two layouts, all UI thread should be terminated.



                                                                If you use AsynTask, then you can easily call .cancel() method inside onDestroy() method of current activity.



                                                                @Override
                                                                protected void onDestroy (){
                                                                removeDialog(DIALOG_LOGIN_ID); // remove loading dialog
                                                                if (loginTask != null){
                                                                if (loginTask.getStatus() != AsyncTask.Status.FINISHED)
                                                                loginTask.cancel(true); //cancel AsyncTask
                                                                }
                                                                super.onDestroy();
                                                                }


                                                                For AsyncTask, read more in "Cancelling a task" section at here.



                                                                Update:
                                                                Added condition to check status, as it can be only cancelled if it is in running state.
                                                                Also note that the AsyncTask can only be executed one time.







                                                                share|improve this answer














                                                                share|improve this answer



                                                                share|improve this answer








                                                                edited Aug 3 '11 at 10:04

























                                                                answered Aug 3 '11 at 5:41









                                                                VikasVikas

                                                                13k32101158




                                                                13k32101158























                                                                    2














                                                                    Tried to implement jfelectron's solution because it is a "rock-solid solution to these issues that conforms with the 'Android Way' of things" but it took some time to look up and put together all the elements mentioned. Ended up with this slightly different, and I think more elegant, solution posted here in it's entirety.



                                                                    Uses an IntentService fired from an activity to perform the long running task on a separate thread. The service fires back sticky Broadcast Intents to the activity which update the dialog. The Activity uses showDialog(), onCreateDialog() and onPrepareDialog() to eliminate the need to have persistent data passed in the application object or the savedInstanceState bundle. This should work no matter how your application is interrupted.



                                                                    Activity Class:



                                                                    public class TesterActivity extends Activity {
                                                                    private ProgressDialog mProgressDialog;
                                                                    private static final int PROGRESS_DIALOG = 0;

                                                                    @Override
                                                                    public void onCreate(Bundle savedInstanceState) {
                                                                    super.onCreate(savedInstanceState);
                                                                    setContentView(R.layout.main);

                                                                    Button b = (Button) this.findViewById(R.id.test_button);
                                                                    b.setOnClickListener(new OnClickListener() {
                                                                    public void onClick(View v) {
                                                                    buttonClick();
                                                                    }
                                                                    });
                                                                    }

                                                                    private void buttonClick(){
                                                                    clearPriorBroadcast();
                                                                    showDialog(PROGRESS_DIALOG);
                                                                    Intent svc = new Intent(this, MyService.class);
                                                                    startService(svc);
                                                                    }

                                                                    protected Dialog onCreateDialog(int id) {
                                                                    switch(id) {
                                                                    case PROGRESS_DIALOG:
                                                                    mProgressDialog = new ProgressDialog(TesterActivity.this);
                                                                    mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
                                                                    mProgressDialog.setMax(MyService.MAX_COUNTER);
                                                                    mProgressDialog.setMessage("Processing...");
                                                                    return mProgressDialog;
                                                                    default:
                                                                    return null;
                                                                    }
                                                                    }

                                                                    @Override
                                                                    protected void onPrepareDialog(int id, Dialog dialog) {
                                                                    switch(id) {
                                                                    case PROGRESS_DIALOG:
                                                                    // setup a broadcast receiver to receive update events from the long running process
                                                                    IntentFilter filter = new IntentFilter();
                                                                    filter.addAction(MyService.BG_PROCESS_INTENT);
                                                                    registerReceiver(new MyBroadcastReceiver(), filter);
                                                                    break;
                                                                    }
                                                                    }

                                                                    public class MyBroadcastReceiver extends BroadcastReceiver{
                                                                    @Override
                                                                    public void onReceive(Context context, Intent intent) {
                                                                    if (intent.hasExtra(MyService.KEY_COUNTER)){
                                                                    int count = intent.getIntExtra(MyService.KEY_COUNTER, 0);
                                                                    mProgressDialog.setProgress(count);
                                                                    if (count >= MyService.MAX_COUNTER){
                                                                    dismissDialog(PROGRESS_DIALOG);
                                                                    }
                                                                    }
                                                                    }
                                                                    }

                                                                    /*
                                                                    * Sticky broadcasts persist and any prior broadcast will trigger in the
                                                                    * broadcast receiver as soon as it is registered.
                                                                    * To clear any prior broadcast this code sends a blank broadcast to clear
                                                                    * the last sticky broadcast.
                                                                    * This broadcast has no extras it will be ignored in the broadcast receiver
                                                                    * setup in onPrepareDialog()
                                                                    */
                                                                    private void clearPriorBroadcast(){
                                                                    Intent broadcastIntent = new Intent();
                                                                    broadcastIntent.setAction(MyService.BG_PROCESS_INTENT);
                                                                    sendStickyBroadcast(broadcastIntent);
                                                                    }}


                                                                    IntentService Class:



                                                                    public class MyService extends IntentService {

                                                                    public static final String BG_PROCESS_INTENT = "com.mindspiker.Tester.MyService.TEST";
                                                                    public static final String KEY_COUNTER = "counter";
                                                                    public static final int MAX_COUNTER = 100;

                                                                    public MyService() {
                                                                    super("");
                                                                    }

                                                                    @Override
                                                                    protected void onHandleIntent(Intent intent) {
                                                                    for (int i = 0; i <= MAX_COUNTER; i++) {
                                                                    Log.e("Service Example", " " + i);
                                                                    try {
                                                                    Thread.sleep(100);
                                                                    } catch (InterruptedException e) {
                                                                    e.printStackTrace();
                                                                    }

                                                                    Intent broadcastIntent = new Intent();
                                                                    broadcastIntent.setAction(BG_PROCESS_INTENT);
                                                                    broadcastIntent.putExtra(KEY_COUNTER, i);
                                                                    sendStickyBroadcast(broadcastIntent);
                                                                    }
                                                                    }}


                                                                    Manifest file entries:



                                                                    before application section:



                                                                    uses-permission android:name="com.mindspiker.Tester.MyService.TEST"
                                                                    uses-permission android:name="android.permission.BROADCAST_STICKY"


                                                                    inside application section



                                                                    service android:name=".MyService"





                                                                    share|improve this answer






























                                                                      2














                                                                      Tried to implement jfelectron's solution because it is a "rock-solid solution to these issues that conforms with the 'Android Way' of things" but it took some time to look up and put together all the elements mentioned. Ended up with this slightly different, and I think more elegant, solution posted here in it's entirety.



                                                                      Uses an IntentService fired from an activity to perform the long running task on a separate thread. The service fires back sticky Broadcast Intents to the activity which update the dialog. The Activity uses showDialog(), onCreateDialog() and onPrepareDialog() to eliminate the need to have persistent data passed in the application object or the savedInstanceState bundle. This should work no matter how your application is interrupted.



                                                                      Activity Class:



                                                                      public class TesterActivity extends Activity {
                                                                      private ProgressDialog mProgressDialog;
                                                                      private static final int PROGRESS_DIALOG = 0;

                                                                      @Override
                                                                      public void onCreate(Bundle savedInstanceState) {
                                                                      super.onCreate(savedInstanceState);
                                                                      setContentView(R.layout.main);

                                                                      Button b = (Button) this.findViewById(R.id.test_button);
                                                                      b.setOnClickListener(new OnClickListener() {
                                                                      public void onClick(View v) {
                                                                      buttonClick();
                                                                      }
                                                                      });
                                                                      }

                                                                      private void buttonClick(){
                                                                      clearPriorBroadcast();
                                                                      showDialog(PROGRESS_DIALOG);
                                                                      Intent svc = new Intent(this, MyService.class);
                                                                      startService(svc);
                                                                      }

                                                                      protected Dialog onCreateDialog(int id) {
                                                                      switch(id) {
                                                                      case PROGRESS_DIALOG:
                                                                      mProgressDialog = new ProgressDialog(TesterActivity.this);
                                                                      mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
                                                                      mProgressDialog.setMax(MyService.MAX_COUNTER);
                                                                      mProgressDialog.setMessage("Processing...");
                                                                      return mProgressDialog;
                                                                      default:
                                                                      return null;
                                                                      }
                                                                      }

                                                                      @Override
                                                                      protected void onPrepareDialog(int id, Dialog dialog) {
                                                                      switch(id) {
                                                                      case PROGRESS_DIALOG:
                                                                      // setup a broadcast receiver to receive update events from the long running process
                                                                      IntentFilter filter = new IntentFilter();
                                                                      filter.addAction(MyService.BG_PROCESS_INTENT);
                                                                      registerReceiver(new MyBroadcastReceiver(), filter);
                                                                      break;
                                                                      }
                                                                      }

                                                                      public class MyBroadcastReceiver extends BroadcastReceiver{
                                                                      @Override
                                                                      public void onReceive(Context context, Intent intent) {
                                                                      if (intent.hasExtra(MyService.KEY_COUNTER)){
                                                                      int count = intent.getIntExtra(MyService.KEY_COUNTER, 0);
                                                                      mProgressDialog.setProgress(count);
                                                                      if (count >= MyService.MAX_COUNTER){
                                                                      dismissDialog(PROGRESS_DIALOG);
                                                                      }
                                                                      }
                                                                      }
                                                                      }

                                                                      /*
                                                                      * Sticky broadcasts persist and any prior broadcast will trigger in the
                                                                      * broadcast receiver as soon as it is registered.
                                                                      * To clear any prior broadcast this code sends a blank broadcast to clear
                                                                      * the last sticky broadcast.
                                                                      * This broadcast has no extras it will be ignored in the broadcast receiver
                                                                      * setup in onPrepareDialog()
                                                                      */
                                                                      private void clearPriorBroadcast(){
                                                                      Intent broadcastIntent = new Intent();
                                                                      broadcastIntent.setAction(MyService.BG_PROCESS_INTENT);
                                                                      sendStickyBroadcast(broadcastIntent);
                                                                      }}


                                                                      IntentService Class:



                                                                      public class MyService extends IntentService {

                                                                      public static final String BG_PROCESS_INTENT = "com.mindspiker.Tester.MyService.TEST";
                                                                      public static final String KEY_COUNTER = "counter";
                                                                      public static final int MAX_COUNTER = 100;

                                                                      public MyService() {
                                                                      super("");
                                                                      }

                                                                      @Override
                                                                      protected void onHandleIntent(Intent intent) {
                                                                      for (int i = 0; i <= MAX_COUNTER; i++) {
                                                                      Log.e("Service Example", " " + i);
                                                                      try {
                                                                      Thread.sleep(100);
                                                                      } catch (InterruptedException e) {
                                                                      e.printStackTrace();
                                                                      }

                                                                      Intent broadcastIntent = new Intent();
                                                                      broadcastIntent.setAction(BG_PROCESS_INTENT);
                                                                      broadcastIntent.putExtra(KEY_COUNTER, i);
                                                                      sendStickyBroadcast(broadcastIntent);
                                                                      }
                                                                      }}


                                                                      Manifest file entries:



                                                                      before application section:



                                                                      uses-permission android:name="com.mindspiker.Tester.MyService.TEST"
                                                                      uses-permission android:name="android.permission.BROADCAST_STICKY"


                                                                      inside application section



                                                                      service android:name=".MyService"





                                                                      share|improve this answer




























                                                                        2












                                                                        2








                                                                        2







                                                                        Tried to implement jfelectron's solution because it is a "rock-solid solution to these issues that conforms with the 'Android Way' of things" but it took some time to look up and put together all the elements mentioned. Ended up with this slightly different, and I think more elegant, solution posted here in it's entirety.



                                                                        Uses an IntentService fired from an activity to perform the long running task on a separate thread. The service fires back sticky Broadcast Intents to the activity which update the dialog. The Activity uses showDialog(), onCreateDialog() and onPrepareDialog() to eliminate the need to have persistent data passed in the application object or the savedInstanceState bundle. This should work no matter how your application is interrupted.



                                                                        Activity Class:



                                                                        public class TesterActivity extends Activity {
                                                                        private ProgressDialog mProgressDialog;
                                                                        private static final int PROGRESS_DIALOG = 0;

                                                                        @Override
                                                                        public void onCreate(Bundle savedInstanceState) {
                                                                        super.onCreate(savedInstanceState);
                                                                        setContentView(R.layout.main);

                                                                        Button b = (Button) this.findViewById(R.id.test_button);
                                                                        b.setOnClickListener(new OnClickListener() {
                                                                        public void onClick(View v) {
                                                                        buttonClick();
                                                                        }
                                                                        });
                                                                        }

                                                                        private void buttonClick(){
                                                                        clearPriorBroadcast();
                                                                        showDialog(PROGRESS_DIALOG);
                                                                        Intent svc = new Intent(this, MyService.class);
                                                                        startService(svc);
                                                                        }

                                                                        protected Dialog onCreateDialog(int id) {
                                                                        switch(id) {
                                                                        case PROGRESS_DIALOG:
                                                                        mProgressDialog = new ProgressDialog(TesterActivity.this);
                                                                        mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
                                                                        mProgressDialog.setMax(MyService.MAX_COUNTER);
                                                                        mProgressDialog.setMessage("Processing...");
                                                                        return mProgressDialog;
                                                                        default:
                                                                        return null;
                                                                        }
                                                                        }

                                                                        @Override
                                                                        protected void onPrepareDialog(int id, Dialog dialog) {
                                                                        switch(id) {
                                                                        case PROGRESS_DIALOG:
                                                                        // setup a broadcast receiver to receive update events from the long running process
                                                                        IntentFilter filter = new IntentFilter();
                                                                        filter.addAction(MyService.BG_PROCESS_INTENT);
                                                                        registerReceiver(new MyBroadcastReceiver(), filter);
                                                                        break;
                                                                        }
                                                                        }

                                                                        public class MyBroadcastReceiver extends BroadcastReceiver{
                                                                        @Override
                                                                        public void onReceive(Context context, Intent intent) {
                                                                        if (intent.hasExtra(MyService.KEY_COUNTER)){
                                                                        int count = intent.getIntExtra(MyService.KEY_COUNTER, 0);
                                                                        mProgressDialog.setProgress(count);
                                                                        if (count >= MyService.MAX_COUNTER){
                                                                        dismissDialog(PROGRESS_DIALOG);
                                                                        }
                                                                        }
                                                                        }
                                                                        }

                                                                        /*
                                                                        * Sticky broadcasts persist and any prior broadcast will trigger in the
                                                                        * broadcast receiver as soon as it is registered.
                                                                        * To clear any prior broadcast this code sends a blank broadcast to clear
                                                                        * the last sticky broadcast.
                                                                        * This broadcast has no extras it will be ignored in the broadcast receiver
                                                                        * setup in onPrepareDialog()
                                                                        */
                                                                        private void clearPriorBroadcast(){
                                                                        Intent broadcastIntent = new Intent();
                                                                        broadcastIntent.setAction(MyService.BG_PROCESS_INTENT);
                                                                        sendStickyBroadcast(broadcastIntent);
                                                                        }}


                                                                        IntentService Class:



                                                                        public class MyService extends IntentService {

                                                                        public static final String BG_PROCESS_INTENT = "com.mindspiker.Tester.MyService.TEST";
                                                                        public static final String KEY_COUNTER = "counter";
                                                                        public static final int MAX_COUNTER = 100;

                                                                        public MyService() {
                                                                        super("");
                                                                        }

                                                                        @Override
                                                                        protected void onHandleIntent(Intent intent) {
                                                                        for (int i = 0; i <= MAX_COUNTER; i++) {
                                                                        Log.e("Service Example", " " + i);
                                                                        try {
                                                                        Thread.sleep(100);
                                                                        } catch (InterruptedException e) {
                                                                        e.printStackTrace();
                                                                        }

                                                                        Intent broadcastIntent = new Intent();
                                                                        broadcastIntent.setAction(BG_PROCESS_INTENT);
                                                                        broadcastIntent.putExtra(KEY_COUNTER, i);
                                                                        sendStickyBroadcast(broadcastIntent);
                                                                        }
                                                                        }}


                                                                        Manifest file entries:



                                                                        before application section:



                                                                        uses-permission android:name="com.mindspiker.Tester.MyService.TEST"
                                                                        uses-permission android:name="android.permission.BROADCAST_STICKY"


                                                                        inside application section



                                                                        service android:name=".MyService"





                                                                        share|improve this answer















                                                                        Tried to implement jfelectron's solution because it is a "rock-solid solution to these issues that conforms with the 'Android Way' of things" but it took some time to look up and put together all the elements mentioned. Ended up with this slightly different, and I think more elegant, solution posted here in it's entirety.



                                                                        Uses an IntentService fired from an activity to perform the long running task on a separate thread. The service fires back sticky Broadcast Intents to the activity which update the dialog. The Activity uses showDialog(), onCreateDialog() and onPrepareDialog() to eliminate the need to have persistent data passed in the application object or the savedInstanceState bundle. This should work no matter how your application is interrupted.



                                                                        Activity Class:



                                                                        public class TesterActivity extends Activity {
                                                                        private ProgressDialog mProgressDialog;
                                                                        private static final int PROGRESS_DIALOG = 0;

                                                                        @Override
                                                                        public void onCreate(Bundle savedInstanceState) {
                                                                        super.onCreate(savedInstanceState);
                                                                        setContentView(R.layout.main);

                                                                        Button b = (Button) this.findViewById(R.id.test_button);
                                                                        b.setOnClickListener(new OnClickListener() {
                                                                        public void onClick(View v) {
                                                                        buttonClick();
                                                                        }
                                                                        });
                                                                        }

                                                                        private void buttonClick(){
                                                                        clearPriorBroadcast();
                                                                        showDialog(PROGRESS_DIALOG);
                                                                        Intent svc = new Intent(this, MyService.class);
                                                                        startService(svc);
                                                                        }

                                                                        protected Dialog onCreateDialog(int id) {
                                                                        switch(id) {
                                                                        case PROGRESS_DIALOG:
                                                                        mProgressDialog = new ProgressDialog(TesterActivity.this);
                                                                        mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
                                                                        mProgressDialog.setMax(MyService.MAX_COUNTER);
                                                                        mProgressDialog.setMessage("Processing...");
                                                                        return mProgressDialog;
                                                                        default:
                                                                        return null;
                                                                        }
                                                                        }

                                                                        @Override
                                                                        protected void onPrepareDialog(int id, Dialog dialog) {
                                                                        switch(id) {
                                                                        case PROGRESS_DIALOG:
                                                                        // setup a broadcast receiver to receive update events from the long running process
                                                                        IntentFilter filter = new IntentFilter();
                                                                        filter.addAction(MyService.BG_PROCESS_INTENT);
                                                                        registerReceiver(new MyBroadcastReceiver(), filter);
                                                                        break;
                                                                        }
                                                                        }

                                                                        public class MyBroadcastReceiver extends BroadcastReceiver{
                                                                        @Override
                                                                        public void onReceive(Context context, Intent intent) {
                                                                        if (intent.hasExtra(MyService.KEY_COUNTER)){
                                                                        int count = intent.getIntExtra(MyService.KEY_COUNTER, 0);
                                                                        mProgressDialog.setProgress(count);
                                                                        if (count >= MyService.MAX_COUNTER){
                                                                        dismissDialog(PROGRESS_DIALOG);
                                                                        }
                                                                        }
                                                                        }
                                                                        }

                                                                        /*
                                                                        * Sticky broadcasts persist and any prior broadcast will trigger in the
                                                                        * broadcast receiver as soon as it is registered.
                                                                        * To clear any prior broadcast this code sends a blank broadcast to clear
                                                                        * the last sticky broadcast.
                                                                        * This broadcast has no extras it will be ignored in the broadcast receiver
                                                                        * setup in onPrepareDialog()
                                                                        */
                                                                        private void clearPriorBroadcast(){
                                                                        Intent broadcastIntent = new Intent();
                                                                        broadcastIntent.setAction(MyService.BG_PROCESS_INTENT);
                                                                        sendStickyBroadcast(broadcastIntent);
                                                                        }}


                                                                        IntentService Class:



                                                                        public class MyService extends IntentService {

                                                                        public static final String BG_PROCESS_INTENT = "com.mindspiker.Tester.MyService.TEST";
                                                                        public static final String KEY_COUNTER = "counter";
                                                                        public static final int MAX_COUNTER = 100;

                                                                        public MyService() {
                                                                        super("");
                                                                        }

                                                                        @Override
                                                                        protected void onHandleIntent(Intent intent) {
                                                                        for (int i = 0; i <= MAX_COUNTER; i++) {
                                                                        Log.e("Service Example", " " + i);
                                                                        try {
                                                                        Thread.sleep(100);
                                                                        } catch (InterruptedException e) {
                                                                        e.printStackTrace();
                                                                        }

                                                                        Intent broadcastIntent = new Intent();
                                                                        broadcastIntent.setAction(BG_PROCESS_INTENT);
                                                                        broadcastIntent.putExtra(KEY_COUNTER, i);
                                                                        sendStickyBroadcast(broadcastIntent);
                                                                        }
                                                                        }}


                                                                        Manifest file entries:



                                                                        before application section:



                                                                        uses-permission android:name="com.mindspiker.Tester.MyService.TEST"
                                                                        uses-permission android:name="android.permission.BROADCAST_STICKY"


                                                                        inside application section



                                                                        service android:name=".MyService"






                                                                        share|improve this answer














                                                                        share|improve this answer



                                                                        share|improve this answer








                                                                        edited Apr 27 '12 at 4:50









                                                                        Lucifer

                                                                        26.4k1574123




                                                                        26.4k1574123










                                                                        answered Nov 10 '11 at 2:23









                                                                        MindSpikerMindSpiker

                                                                        98311019




                                                                        98311019























                                                                            2














                                                                            This is my proposed solution:




                                                                            • Move the AsyncTask or Thread to a retained Fragment, as explained here. I believe it is a good practice to move all network calls to fragments. If you are already using fragments, one of them could be made responsible for the calls. Otherwise, you can create a fragment just for doing the request, as the linked article proposes.

                                                                            • The fragment will use a listener interface to signal the task completion/failure. You don't have to worry for orientation changes there. The fragment will always have the correct link to the current activity and progress dialog can be safely resumed.

                                                                            • Make your progress dialog a member of your class. In fact you should do that for all dialogs. In the onPause method you should dismiss them, otherwise you will leak a window on the configuration change. The busy state should be kept by the fragment. When the fragment is attached to the activity, you can bring up the progress dialog again, if the call is still running. A void showProgressDialog() method can be added to the fragment-activity listener interface for this purpose.






                                                                            share|improve this answer


























                                                                            • Perfect solution, but don't understand why this answer is overshadowed from others !!!

                                                                              – blackkara
                                                                              Feb 28 '17 at 3:18
















                                                                            2














                                                                            This is my proposed solution:




                                                                            • Move the AsyncTask or Thread to a retained Fragment, as explained here. I believe it is a good practice to move all network calls to fragments. If you are already using fragments, one of them could be made responsible for the calls. Otherwise, you can create a fragment just for doing the request, as the linked article proposes.

                                                                            • The fragment will use a listener interface to signal the task completion/failure. You don't have to worry for orientation changes there. The fragment will always have the correct link to the current activity and progress dialog can be safely resumed.

                                                                            • Make your progress dialog a member of your class. In fact you should do that for all dialogs. In the onPause method you should dismiss them, otherwise you will leak a window on the configuration change. The busy state should be kept by the fragment. When the fragment is attached to the activity, you can bring up the progress dialog again, if the call is still running. A void showProgressDialog() method can be added to the fragment-activity listener interface for this purpose.






                                                                            share|improve this answer


























                                                                            • Perfect solution, but don't understand why this answer is overshadowed from others !!!

                                                                              – blackkara
                                                                              Feb 28 '17 at 3:18














                                                                            2












                                                                            2








                                                                            2







                                                                            This is my proposed solution:




                                                                            • Move the AsyncTask or Thread to a retained Fragment, as explained here. I believe it is a good practice to move all network calls to fragments. If you are already using fragments, one of them could be made responsible for the calls. Otherwise, you can create a fragment just for doing the request, as the linked article proposes.

                                                                            • The fragment will use a listener interface to signal the task completion/failure. You don't have to worry for orientation changes there. The fragment will always have the correct link to the current activity and progress dialog can be safely resumed.

                                                                            • Make your progress dialog a member of your class. In fact you should do that for all dialogs. In the onPause method you should dismiss them, otherwise you will leak a window on the configuration change. The busy state should be kept by the fragment. When the fragment is attached to the activity, you can bring up the progress dialog again, if the call is still running. A void showProgressDialog() method can be added to the fragment-activity listener interface for this purpose.






                                                                            share|improve this answer















                                                                            This is my proposed solution:




                                                                            • Move the AsyncTask or Thread to a retained Fragment, as explained here. I believe it is a good practice to move all network calls to fragments. If you are already using fragments, one of them could be made responsible for the calls. Otherwise, you can create a fragment just for doing the request, as the linked article proposes.

                                                                            • The fragment will use a listener interface to signal the task completion/failure. You don't have to worry for orientation changes there. The fragment will always have the correct link to the current activity and progress dialog can be safely resumed.

                                                                            • Make your progress dialog a member of your class. In fact you should do that for all dialogs. In the onPause method you should dismiss them, otherwise you will leak a window on the configuration change. The busy state should be kept by the fragment. When the fragment is attached to the activity, you can bring up the progress dialog again, if the call is still running. A void showProgressDialog() method can be added to the fragment-activity listener interface for this purpose.







                                                                            share|improve this answer














                                                                            share|improve this answer



                                                                            share|improve this answer








                                                                            edited Jun 26 '14 at 15:33

























                                                                            answered Jun 26 '14 at 14:58









                                                                            kgiannakakiskgiannakakis

                                                                            87.5k23144185




                                                                            87.5k23144185













                                                                            • Perfect solution, but don't understand why this answer is overshadowed from others !!!

                                                                              – blackkara
                                                                              Feb 28 '17 at 3:18



















                                                                            • Perfect solution, but don't understand why this answer is overshadowed from others !!!

                                                                              – blackkara
                                                                              Feb 28 '17 at 3:18

















                                                                            Perfect solution, but don't understand why this answer is overshadowed from others !!!

                                                                            – blackkara
                                                                            Feb 28 '17 at 3:18





                                                                            Perfect solution, but don't understand why this answer is overshadowed from others !!!

                                                                            – blackkara
                                                                            Feb 28 '17 at 3:18











                                                                            1














                                                                            I've tried EVERYTHING. Spent days experimenting. I didn't want to block the activity from rotating. My scenario was:




                                                                            1. A progress dialog showing dynamic information to the user. E.g.: "Connecting to server...", "Downloading data...", etc.

                                                                            2. A thread doing the heavy stuff and updating the dialog

                                                                            3. Updating the UI with the results at the end.


                                                                            The problem was, when rotating the screen, every solution on the book failed. Even with the AsyncTask class, which is the correct Android way of dealing with this situations. When rotating the screen, the current Context that the starting thread is working with, is gone, and that messes up with the dialog that is showing. The problem was always the Dialog, no matter how many tricks I added to the code (passing new contexts to running threads, retaining thread states through rotations, etc...). The code complexity at the end was always huge and there was always something that could go wrong.



                                                                            The only solution that worked for me was the Activity/Dialog trick. It's simple and genius and it's all rotation proof:




                                                                            1. Instead of creating a Dialog and ask to show it, create an Activity that has been set in the manifest with android:theme="@android:style/Theme.Dialog". So, it just looks like a dialog.


                                                                            2. Replace showDialog(DIALOG_ID) with startActivityForResult(yourActivityDialog, yourCode);


                                                                            3. Use onActivityResult in the calling Activity to get the results from the executing thread (even the errors) and update the UI.


                                                                            4. On your 'ActivityDialog', use threads or AsyncTask to execute long tasks and onRetainNonConfigurationInstance to save "dialog" state when rotating the screen.



                                                                            This is fast and works fine. I still use dialogs for other tasks and the AsyncTask for something that doesn't require a constant dialog on screen. But with this scenario, I always go for the Activity/Dialog pattern.



                                                                            And, I didn't try it, but it's even possible to block that Activity/Dialog from rotating, when the thread is running, speeding things up, while allowing the calling Activity to rotate.






                                                                            share|improve this answer
























                                                                            • Nice except that parameters must be passed through an Intent, which is more restrictive than the Object allowed by AsyncTask

                                                                              – rds
                                                                              Mar 29 '11 at 21:24











                                                                            • @Rui I too used this method for the last year. It has now occurred to me though that this is also incorrect. Why would Google even have a Dialog if this was the way to 'fix' this issue? The problem I see is that if you open ActivityB (Theme.Dialog) from ActivityA then ActivityA is moved down on the Activity stack thus is marked as ready to kill by the OS if necessary. Therefore, if you have a long running process and are showing some sort of faux progress 'dialog' and it took too long and memory ran low... ActivityA is killed and there is nothing to come back too upon progress complete.

                                                                              – rf43
                                                                              Oct 13 '11 at 0:47


















                                                                            1














                                                                            I've tried EVERYTHING. Spent days experimenting. I didn't want to block the activity from rotating. My scenario was:




                                                                            1. A progress dialog showing dynamic information to the user. E.g.: "Connecting to server...", "Downloading data...", etc.

                                                                            2. A thread doing the heavy stuff and updating the dialog

                                                                            3. Updating the UI with the results at the end.


                                                                            The problem was, when rotating the screen, every solution on the book failed. Even with the AsyncTask class, which is the correct Android way of dealing with this situations. When rotating the screen, the current Context that the starting thread is working with, is gone, and that messes up with the dialog that is showing. The problem was always the Dialog, no matter how many tricks I added to the code (passing new contexts to running threads, retaining thread states through rotations, etc...). The code complexity at the end was always huge and there was always something that could go wrong.



                                                                            The only solution that worked for me was the Activity/Dialog trick. It's simple and genius and it's all rotation proof:




                                                                            1. Instead of creating a Dialog and ask to show it, create an Activity that has been set in the manifest with android:theme="@android:style/Theme.Dialog". So, it just looks like a dialog.


                                                                            2. Replace showDialog(DIALOG_ID) with startActivityForResult(yourActivityDialog, yourCode);


                                                                            3. Use onActivityResult in the calling Activity to get the results from the executing thread (even the errors) and update the UI.


                                                                            4. On your 'ActivityDialog', use threads or AsyncTask to execute long tasks and onRetainNonConfigurationInstance to save "dialog" state when rotating the screen.



                                                                            This is fast and works fine. I still use dialogs for other tasks and the AsyncTask for something that doesn't require a constant dialog on screen. But with this scenario, I always go for the Activity/Dialog pattern.



                                                                            And, I didn't try it, but it's even possible to block that Activity/Dialog from rotating, when the thread is running, speeding things up, while allowing the calling Activity to rotate.






                                                                            share|improve this answer
























                                                                            • Nice except that parameters must be passed through an Intent, which is more restrictive than the Object allowed by AsyncTask

                                                                              – rds
                                                                              Mar 29 '11 at 21:24











                                                                            • @Rui I too used this method for the last year. It has now occurred to me though that this is also incorrect. Why would Google even have a Dialog if this was the way to 'fix' this issue? The problem I see is that if you open ActivityB (Theme.Dialog) from ActivityA then ActivityA is moved down on the Activity stack thus is marked as ready to kill by the OS if necessary. Therefore, if you have a long running process and are showing some sort of faux progress 'dialog' and it took too long and memory ran low... ActivityA is killed and there is nothing to come back too upon progress complete.

                                                                              – rf43
                                                                              Oct 13 '11 at 0:47
















                                                                            1












                                                                            1








                                                                            1







                                                                            I've tried EVERYTHING. Spent days experimenting. I didn't want to block the activity from rotating. My scenario was:




                                                                            1. A progress dialog showing dynamic information to the user. E.g.: "Connecting to server...", "Downloading data...", etc.

                                                                            2. A thread doing the heavy stuff and updating the dialog

                                                                            3. Updating the UI with the results at the end.


                                                                            The problem was, when rotating the screen, every solution on the book failed. Even with the AsyncTask class, which is the correct Android way of dealing with this situations. When rotating the screen, the current Context that the starting thread is working with, is gone, and that messes up with the dialog that is showing. The problem was always the Dialog, no matter how many tricks I added to the code (passing new contexts to running threads, retaining thread states through rotations, etc...). The code complexity at the end was always huge and there was always something that could go wrong.



                                                                            The only solution that worked for me was the Activity/Dialog trick. It's simple and genius and it's all rotation proof:




                                                                            1. Instead of creating a Dialog and ask to show it, create an Activity that has been set in the manifest with android:theme="@android:style/Theme.Dialog". So, it just looks like a dialog.


                                                                            2. Replace showDialog(DIALOG_ID) with startActivityForResult(yourActivityDialog, yourCode);


                                                                            3. Use onActivityResult in the calling Activity to get the results from the executing thread (even the errors) and update the UI.


                                                                            4. On your 'ActivityDialog', use threads or AsyncTask to execute long tasks and onRetainNonConfigurationInstance to save "dialog" state when rotating the screen.



                                                                            This is fast and works fine. I still use dialogs for other tasks and the AsyncTask for something that doesn't require a constant dialog on screen. But with this scenario, I always go for the Activity/Dialog pattern.



                                                                            And, I didn't try it, but it's even possible to block that Activity/Dialog from rotating, when the thread is running, speeding things up, while allowing the calling Activity to rotate.






                                                                            share|improve this answer













                                                                            I've tried EVERYTHING. Spent days experimenting. I didn't want to block the activity from rotating. My scenario was:




                                                                            1. A progress dialog showing dynamic information to the user. E.g.: "Connecting to server...", "Downloading data...", etc.

                                                                            2. A thread doing the heavy stuff and updating the dialog

                                                                            3. Updating the UI with the results at the end.


                                                                            The problem was, when rotating the screen, every solution on the book failed. Even with the AsyncTask class, which is the correct Android way of dealing with this situations. When rotating the screen, the current Context that the starting thread is working with, is gone, and that messes up with the dialog that is showing. The problem was always the Dialog, no matter how many tricks I added to the code (passing new contexts to running threads, retaining thread states through rotations, etc...). The code complexity at the end was always huge and there was always something that could go wrong.



                                                                            The only solution that worked for me was the Activity/Dialog trick. It's simple and genius and it's all rotation proof:




                                                                            1. Instead of creating a Dialog and ask to show it, create an Activity that has been set in the manifest with android:theme="@android:style/Theme.Dialog". So, it just looks like a dialog.


                                                                            2. Replace showDialog(DIALOG_ID) with startActivityForResult(yourActivityDialog, yourCode);


                                                                            3. Use onActivityResult in the calling Activity to get the results from the executing thread (even the errors) and update the UI.


                                                                            4. On your 'ActivityDialog', use threads or AsyncTask to execute long tasks and onRetainNonConfigurationInstance to save "dialog" state when rotating the screen.



                                                                            This is fast and works fine. I still use dialogs for other tasks and the AsyncTask for something that doesn't require a constant dialog on screen. But with this scenario, I always go for the Activity/Dialog pattern.



                                                                            And, I didn't try it, but it's even possible to block that Activity/Dialog from rotating, when the thread is running, speeding things up, while allowing the calling Activity to rotate.







                                                                            share|improve this answer












                                                                            share|improve this answer



                                                                            share|improve this answer










                                                                            answered Mar 7 '10 at 17:47









                                                                            RuiRui

                                                                            189113




                                                                            189113













                                                                            • Nice except that parameters must be passed through an Intent, which is more restrictive than the Object allowed by AsyncTask

                                                                              – rds
                                                                              Mar 29 '11 at 21:24











                                                                            • @Rui I too used this method for the last year. It has now occurred to me though that this is also incorrect. Why would Google even have a Dialog if this was the way to 'fix' this issue? The problem I see is that if you open ActivityB (Theme.Dialog) from ActivityA then ActivityA is moved down on the Activity stack thus is marked as ready to kill by the OS if necessary. Therefore, if you have a long running process and are showing some sort of faux progress 'dialog' and it took too long and memory ran low... ActivityA is killed and there is nothing to come back too upon progress complete.

                                                                              – rf43
                                                                              Oct 13 '11 at 0:47





















                                                                            • Nice except that parameters must be passed through an Intent, which is more restrictive than the Object allowed by AsyncTask

                                                                              – rds
                                                                              Mar 29 '11 at 21:24











                                                                            • @Rui I too used this method for the last year. It has now occurred to me though that this is also incorrect. Why would Google even have a Dialog if this was the way to 'fix' this issue? The problem I see is that if you open ActivityB (Theme.Dialog) from ActivityA then ActivityA is moved down on the Activity stack thus is marked as ready to kill by the OS if necessary. Therefore, if you have a long running process and are showing some sort of faux progress 'dialog' and it took too long and memory ran low... ActivityA is killed and there is nothing to come back too upon progress complete.

                                                                              – rf43
                                                                              Oct 13 '11 at 0:47



















                                                                            Nice except that parameters must be passed through an Intent, which is more restrictive than the Object allowed by AsyncTask

                                                                            – rds
                                                                            Mar 29 '11 at 21:24





                                                                            Nice except that parameters must be passed through an Intent, which is more restrictive than the Object allowed by AsyncTask

                                                                            – rds
                                                                            Mar 29 '11 at 21:24













                                                                            @Rui I too used this method for the last year. It has now occurred to me though that this is also incorrect. Why would Google even have a Dialog if this was the way to 'fix' this issue? The problem I see is that if you open ActivityB (Theme.Dialog) from ActivityA then ActivityA is moved down on the Activity stack thus is marked as ready to kill by the OS if necessary. Therefore, if you have a long running process and are showing some sort of faux progress 'dialog' and it took too long and memory ran low... ActivityA is killed and there is nothing to come back too upon progress complete.

                                                                            – rf43
                                                                            Oct 13 '11 at 0:47







                                                                            @Rui I too used this method for the last year. It has now occurred to me though that this is also incorrect. Why would Google even have a Dialog if this was the way to 'fix' this issue? The problem I see is that if you open ActivityB (Theme.Dialog) from ActivityA then ActivityA is moved down on the Activity stack thus is marked as ready to kill by the OS if necessary. Therefore, if you have a long running process and are showing some sort of faux progress 'dialog' and it took too long and memory ran low... ActivityA is killed and there is nothing to come back too upon progress complete.

                                                                            – rf43
                                                                            Oct 13 '11 at 0:47













                                                                            1














                                                                            These days there is a much more distinct way to handle these types of issues. The typical approach is:



                                                                            1. Ensure your data is properly seperated from the UI:



                                                                            Anything that is a background process should be in a retained Fragment (set this with Fragment.setRetainInstance(). This becomes your 'persistent data storage' where anything data based that you would like retained is kept. After the orientation change event, this Fragment will still be accessible in its original state through a FragmentManager.findFragmentByTag() call (when you create it you should give it a tag not an ID as it is not attached to a View).



                                                                            See the Handling Runtime Changes developed guide for information about doing this correctly and why it is the best option.



                                                                            2. Ensure you are interfacing correctly and safely between the background processs and your UI:



                                                                            You must reverse your linking process. At the moment your background process attaches itself to a View - instead your View should be attaching itself to the background process. It makes more sense right? The View's action is dependent on the background process, whereas the background process is not dependent on the View.This means changing the link to a standard Listener interface. Say your process (whatever class it is - whether it is an AsyncTask, Runnable or whatever) defines a OnProcessFinishedListener, when the process is done it should call that listener if it exists.



                                                                            This answer is a nice concise description of how to do custom listeners.



                                                                            3. Link your UI into the data process whenever the UI is created (including orientation changes):



                                                                            Now you must worry about interfacing the background task with whatever your current View structure is. If you are handling your orientation changes properly (not the configChanges hack people always recommend), then your Dialog will be recreated by the system. This is important, it means that on the orientation change, all your Dialog's lifecycle methods are recalled. So in any of these methods (onCreateDialog is usually a good place), you could do a call like the following:





                                                                            DataFragment f = getActivity().getFragmentManager().findFragmentByTag("BACKGROUND_TAG");
                                                                            if (f != null) {
                                                                            f.mBackgroundProcess.setOnProcessFinishedListener(new OnProcessFinishedListener() {
                                                                            public void onProcessFinished() {
                                                                            dismiss();
                                                                            }
                                                                            });
                                                                            }


                                                                            See the Fragment lifecycle for deciding where setting the listener best fits in your individual implementation.





                                                                            This is a general approach to providing a robust and complete solution to the generic problem asked in this question. There is probably a few minor pieces missing in this answer depending on your individual scenario, but this is generally the most correct approach for properly handling orientation change events.






                                                                            share|improve this answer






























                                                                              1














                                                                              These days there is a much more distinct way to handle these types of issues. The typical approach is:



                                                                              1. Ensure your data is properly seperated from the UI:



                                                                              Anything that is a background process should be in a retained Fragment (set this with Fragment.setRetainInstance(). This becomes your 'persistent data storage' where anything data based that you would like retained is kept. After the orientation change event, this Fragment will still be accessible in its original state through a FragmentManager.findFragmentByTag() call (when you create it you should give it a tag not an ID as it is not attached to a View).



                                                                              See the Handling Runtime Changes developed guide for information about doing this correctly and why it is the best option.



                                                                              2. Ensure you are interfacing correctly and safely between the background processs and your UI:



                                                                              You must reverse your linking process. At the moment your background process attaches itself to a View - instead your View should be attaching itself to the background process. It makes more sense right? The View's action is dependent on the background process, whereas the background process is not dependent on the View.This means changing the link to a standard Listener interface. Say your process (whatever class it is - whether it is an AsyncTask, Runnable or whatever) defines a OnProcessFinishedListener, when the process is done it should call that listener if it exists.



                                                                              This answer is a nice concise description of how to do custom listeners.



                                                                              3. Link your UI into the data process whenever the UI is created (including orientation changes):



                                                                              Now you must worry about interfacing the background task with whatever your current View structure is. If you are handling your orientation changes properly (not the configChanges hack people always recommend), then your Dialog will be recreated by the system. This is important, it means that on the orientation change, all your Dialog's lifecycle methods are recalled. So in any of these methods (onCreateDialog is usually a good place), you could do a call like the following:





                                                                              DataFragment f = getActivity().getFragmentManager().findFragmentByTag("BACKGROUND_TAG");
                                                                              if (f != null) {
                                                                              f.mBackgroundProcess.setOnProcessFinishedListener(new OnProcessFinishedListener() {
                                                                              public void onProcessFinished() {
                                                                              dismiss();
                                                                              }
                                                                              });
                                                                              }


                                                                              See the Fragment lifecycle for deciding where setting the listener best fits in your individual implementation.





                                                                              This is a general approach to providing a robust and complete solution to the generic problem asked in this question. There is probably a few minor pieces missing in this answer depending on your individual scenario, but this is generally the most correct approach for properly handling orientation change events.






                                                                              share|improve this answer




























                                                                                1












                                                                                1








                                                                                1







                                                                                These days there is a much more distinct way to handle these types of issues. The typical approach is:



                                                                                1. Ensure your data is properly seperated from the UI:



                                                                                Anything that is a background process should be in a retained Fragment (set this with Fragment.setRetainInstance(). This becomes your 'persistent data storage' where anything data based that you would like retained is kept. After the orientation change event, this Fragment will still be accessible in its original state through a FragmentManager.findFragmentByTag() call (when you create it you should give it a tag not an ID as it is not attached to a View).



                                                                                See the Handling Runtime Changes developed guide for information about doing this correctly and why it is the best option.



                                                                                2. Ensure you are interfacing correctly and safely between the background processs and your UI:



                                                                                You must reverse your linking process. At the moment your background process attaches itself to a View - instead your View should be attaching itself to the background process. It makes more sense right? The View's action is dependent on the background process, whereas the background process is not dependent on the View.This means changing the link to a standard Listener interface. Say your process (whatever class it is - whether it is an AsyncTask, Runnable or whatever) defines a OnProcessFinishedListener, when the process is done it should call that listener if it exists.



                                                                                This answer is a nice concise description of how to do custom listeners.



                                                                                3. Link your UI into the data process whenever the UI is created (including orientation changes):



                                                                                Now you must worry about interfacing the background task with whatever your current View structure is. If you are handling your orientation changes properly (not the configChanges hack people always recommend), then your Dialog will be recreated by the system. This is important, it means that on the orientation change, all your Dialog's lifecycle methods are recalled. So in any of these methods (onCreateDialog is usually a good place), you could do a call like the following:





                                                                                DataFragment f = getActivity().getFragmentManager().findFragmentByTag("BACKGROUND_TAG");
                                                                                if (f != null) {
                                                                                f.mBackgroundProcess.setOnProcessFinishedListener(new OnProcessFinishedListener() {
                                                                                public void onProcessFinished() {
                                                                                dismiss();
                                                                                }
                                                                                });
                                                                                }


                                                                                See the Fragment lifecycle for deciding where setting the listener best fits in your individual implementation.





                                                                                This is a general approach to providing a robust and complete solution to the generic problem asked in this question. There is probably a few minor pieces missing in this answer depending on your individual scenario, but this is generally the most correct approach for properly handling orientation change events.






                                                                                share|improve this answer















                                                                                These days there is a much more distinct way to handle these types of issues. The typical approach is:



                                                                                1. Ensure your data is properly seperated from the UI:



                                                                                Anything that is a background process should be in a retained Fragment (set this with Fragment.setRetainInstance(). This becomes your 'persistent data storage' where anything data based that you would like retained is kept. After the orientation change event, this Fragment will still be accessible in its original state through a FragmentManager.findFragmentByTag() call (when you create it you should give it a tag not an ID as it is not attached to a View).



                                                                                See the Handling Runtime Changes developed guide for information about doing this correctly and why it is the best option.



                                                                                2. Ensure you are interfacing correctly and safely between the background processs and your UI:



                                                                                You must reverse your linking process. At the moment your background process attaches itself to a View - instead your View should be attaching itself to the background process. It makes more sense right? The View's action is dependent on the background process, whereas the background process is not dependent on the View.This means changing the link to a standard Listener interface. Say your process (whatever class it is - whether it is an AsyncTask, Runnable or whatever) defines a OnProcessFinishedListener, when the process is done it should call that listener if it exists.



                                                                                This answer is a nice concise description of how to do custom listeners.



                                                                                3. Link your UI into the data process whenever the UI is created (including orientation changes):



                                                                                Now you must worry about interfacing the background task with whatever your current View structure is. If you are handling your orientation changes properly (not the configChanges hack people always recommend), then your Dialog will be recreated by the system. This is important, it means that on the orientation change, all your Dialog's lifecycle methods are recalled. So in any of these methods (onCreateDialog is usually a good place), you could do a call like the following:





                                                                                DataFragment f = getActivity().getFragmentManager().findFragmentByTag("BACKGROUND_TAG");
                                                                                if (f != null) {
                                                                                f.mBackgroundProcess.setOnProcessFinishedListener(new OnProcessFinishedListener() {
                                                                                public void onProcessFinished() {
                                                                                dismiss();
                                                                                }
                                                                                });
                                                                                }


                                                                                See the Fragment lifecycle for deciding where setting the listener best fits in your individual implementation.





                                                                                This is a general approach to providing a robust and complete solution to the generic problem asked in this question. There is probably a few minor pieces missing in this answer depending on your individual scenario, but this is generally the most correct approach for properly handling orientation change events.







                                                                                share|improve this answer














                                                                                share|improve this answer



                                                                                share|improve this answer








                                                                                edited May 23 '17 at 12:26









                                                                                Community

                                                                                11




                                                                                11










                                                                                answered Nov 19 '14 at 23:50









                                                                                B TB T

                                                                                4,04193041




                                                                                4,04193041























                                                                                    1














                                                                                    I faced the same situation. What I did was get only one instance for my progress dialog in the entire application.



                                                                                    First, I created a DialogSingleton class to get only one instance (Singleton pattern)



                                                                                    public class DialogSingleton
                                                                                    {
                                                                                    private static Dialog dialog;

                                                                                    private static final Object mLock = new Object();
                                                                                    private static DialogSingleton instance;

                                                                                    private DialogSingleton()
                                                                                    {

                                                                                    }

                                                                                    public static DialogSingleton GetInstance()
                                                                                    {
                                                                                    synchronized (mLock)
                                                                                    {
                                                                                    if(instance == null)
                                                                                    {
                                                                                    instance = new DialogSingleton();
                                                                                    }

                                                                                    return instance;
                                                                                    }
                                                                                    }

                                                                                    public void DialogShow(Context context, String title)
                                                                                    {
                                                                                    if(!((Activity)context).isFinishing())
                                                                                    {
                                                                                    dialog = new ProgressDialog(context, 2);

                                                                                    dialog.setCanceledOnTouchOutside(false);

                                                                                    dialog.setTitle(title);

                                                                                    dialog.show();
                                                                                    }
                                                                                    }

                                                                                    public void DialogDismiss(Context context)
                                                                                    {
                                                                                    if(!((Activity)context).isFinishing() && dialog.isShowing())
                                                                                    {
                                                                                    dialog.dismiss();
                                                                                    }
                                                                                    }
                                                                                    }


                                                                                    As I show in this class, I have the progress dialog as attribute. Every time I need to show a progress dialog, I get the unique instance and create a new ProgressDialog.



                                                                                    DialogSingleton.GetInstance().DialogShow(this, "My title here!");


                                                                                    When I am done with the background task, I call again the unique instance and dismiss its dialog.



                                                                                    DialogSingleton.GetInstance().DialogDismiss(this);


                                                                                    I save the background task status in my shared preferences. When I rotate the screen, I ask if I have a task running for this activity: (onCreate)



                                                                                    if(Boolean.parseBoolean(preference.GetValue(IS_TASK_NAME_EXECUTED_KEY, "boolean").toString()))
                                                                                    {
                                                                                    DialogSingleton.GetInstance().DialogShow(this, "Checking credentials!");
                                                                                    } // preference object gets the info from shared preferences (my own implementation to get and put data to shared preferences) and IS_TASK_NAME_EXECUTED_KEY is the key to save this flag (flag to know if this activity has a background task already running).


                                                                                    When I start running a background task:



                                                                                    preference.AddValue(IS_TASK_NAME_EXECUTED_KEY, true, "boolean");

                                                                                    DialogSingleton.GetInstance().DialogShow(this, "My title here!");


                                                                                    When I finish running a background task:



                                                                                    preference.AddValue(IS_TASK_NAME_EXECUTED_KEY, false, "boolean");

                                                                                    DialogSingleton.GetInstance().DialogDismiss(ActivityName.this);


                                                                                    I hope it helps.






                                                                                    share|improve this answer






























                                                                                      1














                                                                                      I faced the same situation. What I did was get only one instance for my progress dialog in the entire application.



                                                                                      First, I created a DialogSingleton class to get only one instance (Singleton pattern)



                                                                                      public class DialogSingleton
                                                                                      {
                                                                                      private static Dialog dialog;

                                                                                      private static final Object mLock = new Object();
                                                                                      private static DialogSingleton instance;

                                                                                      private DialogSingleton()
                                                                                      {

                                                                                      }

                                                                                      public static DialogSingleton GetInstance()
                                                                                      {
                                                                                      synchronized (mLock)
                                                                                      {
                                                                                      if(instance == null)
                                                                                      {
                                                                                      instance = new DialogSingleton();
                                                                                      }

                                                                                      return instance;
                                                                                      }
                                                                                      }

                                                                                      public void DialogShow(Context context, String title)
                                                                                      {
                                                                                      if(!((Activity)context).isFinishing())
                                                                                      {
                                                                                      dialog = new ProgressDialog(context, 2);

                                                                                      dialog.setCanceledOnTouchOutside(false);

                                                                                      dialog.setTitle(title);

                                                                                      dialog.show();
                                                                                      }
                                                                                      }

                                                                                      public void DialogDismiss(Context context)
                                                                                      {
                                                                                      if(!((Activity)context).isFinishing() && dialog.isShowing())
                                                                                      {
                                                                                      dialog.dismiss();
                                                                                      }
                                                                                      }
                                                                                      }


                                                                                      As I show in this class, I have the progress dialog as attribute. Every time I need to show a progress dialog, I get the unique instance and create a new ProgressDialog.



                                                                                      DialogSingleton.GetInstance().DialogShow(this, "My title here!");


                                                                                      When I am done with the background task, I call again the unique instance and dismiss its dialog.



                                                                                      DialogSingleton.GetInstance().DialogDismiss(this);


                                                                                      I save the background task status in my shared preferences. When I rotate the screen, I ask if I have a task running for this activity: (onCreate)



                                                                                      if(Boolean.parseBoolean(preference.GetValue(IS_TASK_NAME_EXECUTED_KEY, "boolean").toString()))
                                                                                      {
                                                                                      DialogSingleton.GetInstance().DialogShow(this, "Checking credentials!");
                                                                                      } // preference object gets the info from shared preferences (my own implementation to get and put data to shared preferences) and IS_TASK_NAME_EXECUTED_KEY is the key to save this flag (flag to know if this activity has a background task already running).


                                                                                      When I start running a background task:



                                                                                      preference.AddValue(IS_TASK_NAME_EXECUTED_KEY, true, "boolean");

                                                                                      DialogSingleton.GetInstance().DialogShow(this, "My title here!");


                                                                                      When I finish running a background task:



                                                                                      preference.AddValue(IS_TASK_NAME_EXECUTED_KEY, false, "boolean");

                                                                                      DialogSingleton.GetInstance().DialogDismiss(ActivityName.this);


                                                                                      I hope it helps.






                                                                                      share|improve this answer




























                                                                                        1












                                                                                        1








                                                                                        1







                                                                                        I faced the same situation. What I did was get only one instance for my progress dialog in the entire application.



                                                                                        First, I created a DialogSingleton class to get only one instance (Singleton pattern)



                                                                                        public class DialogSingleton
                                                                                        {
                                                                                        private static Dialog dialog;

                                                                                        private static final Object mLock = new Object();
                                                                                        private static DialogSingleton instance;

                                                                                        private DialogSingleton()
                                                                                        {

                                                                                        }

                                                                                        public static DialogSingleton GetInstance()
                                                                                        {
                                                                                        synchronized (mLock)
                                                                                        {
                                                                                        if(instance == null)
                                                                                        {
                                                                                        instance = new DialogSingleton();
                                                                                        }

                                                                                        return instance;
                                                                                        }
                                                                                        }

                                                                                        public void DialogShow(Context context, String title)
                                                                                        {
                                                                                        if(!((Activity)context).isFinishing())
                                                                                        {
                                                                                        dialog = new ProgressDialog(context, 2);

                                                                                        dialog.setCanceledOnTouchOutside(false);

                                                                                        dialog.setTitle(title);

                                                                                        dialog.show();
                                                                                        }
                                                                                        }

                                                                                        public void DialogDismiss(Context context)
                                                                                        {
                                                                                        if(!((Activity)context).isFinishing() && dialog.isShowing())
                                                                                        {
                                                                                        dialog.dismiss();
                                                                                        }
                                                                                        }
                                                                                        }


                                                                                        As I show in this class, I have the progress dialog as attribute. Every time I need to show a progress dialog, I get the unique instance and create a new ProgressDialog.



                                                                                        DialogSingleton.GetInstance().DialogShow(this, "My title here!");


                                                                                        When I am done with the background task, I call again the unique instance and dismiss its dialog.



                                                                                        DialogSingleton.GetInstance().DialogDismiss(this);


                                                                                        I save the background task status in my shared preferences. When I rotate the screen, I ask if I have a task running for this activity: (onCreate)



                                                                                        if(Boolean.parseBoolean(preference.GetValue(IS_TASK_NAME_EXECUTED_KEY, "boolean").toString()))
                                                                                        {
                                                                                        DialogSingleton.GetInstance().DialogShow(this, "Checking credentials!");
                                                                                        } // preference object gets the info from shared preferences (my own implementation to get and put data to shared preferences) and IS_TASK_NAME_EXECUTED_KEY is the key to save this flag (flag to know if this activity has a background task already running).


                                                                                        When I start running a background task:



                                                                                        preference.AddValue(IS_TASK_NAME_EXECUTED_KEY, true, "boolean");

                                                                                        DialogSingleton.GetInstance().DialogShow(this, "My title here!");


                                                                                        When I finish running a background task:



                                                                                        preference.AddValue(IS_TASK_NAME_EXECUTED_KEY, false, "boolean");

                                                                                        DialogSingleton.GetInstance().DialogDismiss(ActivityName.this);


                                                                                        I hope it helps.






                                                                                        share|improve this answer















                                                                                        I faced the same situation. What I did was get only one instance for my progress dialog in the entire application.



                                                                                        First, I created a DialogSingleton class to get only one instance (Singleton pattern)



                                                                                        public class DialogSingleton
                                                                                        {
                                                                                        private static Dialog dialog;

                                                                                        private static final Object mLock = new Object();
                                                                                        private static DialogSingleton instance;

                                                                                        private DialogSingleton()
                                                                                        {

                                                                                        }

                                                                                        public static DialogSingleton GetInstance()
                                                                                        {
                                                                                        synchronized (mLock)
                                                                                        {
                                                                                        if(instance == null)
                                                                                        {
                                                                                        instance = new DialogSingleton();
                                                                                        }

                                                                                        return instance;
                                                                                        }
                                                                                        }

                                                                                        public void DialogShow(Context context, String title)
                                                                                        {
                                                                                        if(!((Activity)context).isFinishing())
                                                                                        {
                                                                                        dialog = new ProgressDialog(context, 2);

                                                                                        dialog.setCanceledOnTouchOutside(false);

                                                                                        dialog.setTitle(title);

                                                                                        dialog.show();
                                                                                        }
                                                                                        }

                                                                                        public void DialogDismiss(Context context)
                                                                                        {
                                                                                        if(!((Activity)context).isFinishing() && dialog.isShowing())
                                                                                        {
                                                                                        dialog.dismiss();
                                                                                        }
                                                                                        }
                                                                                        }


                                                                                        As I show in this class, I have the progress dialog as attribute. Every time I need to show a progress dialog, I get the unique instance and create a new ProgressDialog.



                                                                                        DialogSingleton.GetInstance().DialogShow(this, "My title here!");


                                                                                        When I am done with the background task, I call again the unique instance and dismiss its dialog.



                                                                                        DialogSingleton.GetInstance().DialogDismiss(this);


                                                                                        I save the background task status in my shared preferences. When I rotate the screen, I ask if I have a task running for this activity: (onCreate)



                                                                                        if(Boolean.parseBoolean(preference.GetValue(IS_TASK_NAME_EXECUTED_KEY, "boolean").toString()))
                                                                                        {
                                                                                        DialogSingleton.GetInstance().DialogShow(this, "Checking credentials!");
                                                                                        } // preference object gets the info from shared preferences (my own implementation to get and put data to shared preferences) and IS_TASK_NAME_EXECUTED_KEY is the key to save this flag (flag to know if this activity has a background task already running).


                                                                                        When I start running a background task:



                                                                                        preference.AddValue(IS_TASK_NAME_EXECUTED_KEY, true, "boolean");

                                                                                        DialogSingleton.GetInstance().DialogShow(this, "My title here!");


                                                                                        When I finish running a background task:



                                                                                        preference.AddValue(IS_TASK_NAME_EXECUTED_KEY, false, "boolean");

                                                                                        DialogSingleton.GetInstance().DialogDismiss(ActivityName.this);


                                                                                        I hope it helps.







                                                                                        share|improve this answer














                                                                                        share|improve this answer



                                                                                        share|improve this answer








                                                                                        edited Dec 29 '15 at 19:16

























                                                                                        answered Dec 28 '15 at 22:37









                                                                                        deinierdeinier

                                                                                        1507




                                                                                        1507























                                                                                            1














                                                                                            This is a very old question that came up on the sidebar for some reason.



                                                                                            If the background task only needs to survive while the activity is in the foreground, the "new" solution is to host the background thread (or, preferably, AsyncTask) in a retained fragment, as described in this developer guide and numerous Q&As.



                                                                                            A retained fragment survives if the activity is destroyed for a configuration change, but not when the activity is destroyed in the background or back stack. Therefore, the background task should still be interrupted if isChangingConfigurations() is false in onPause().






                                                                                            share|improve this answer






























                                                                                              1














                                                                                              This is a very old question that came up on the sidebar for some reason.



                                                                                              If the background task only needs to survive while the activity is in the foreground, the "new" solution is to host the background thread (or, preferably, AsyncTask) in a retained fragment, as described in this developer guide and numerous Q&As.



                                                                                              A retained fragment survives if the activity is destroyed for a configuration change, but not when the activity is destroyed in the background or back stack. Therefore, the background task should still be interrupted if isChangingConfigurations() is false in onPause().






                                                                                              share|improve this answer




























                                                                                                1












                                                                                                1








                                                                                                1







                                                                                                This is a very old question that came up on the sidebar for some reason.



                                                                                                If the background task only needs to survive while the activity is in the foreground, the "new" solution is to host the background thread (or, preferably, AsyncTask) in a retained fragment, as described in this developer guide and numerous Q&As.



                                                                                                A retained fragment survives if the activity is destroyed for a configuration change, but not when the activity is destroyed in the background or back stack. Therefore, the background task should still be interrupted if isChangingConfigurations() is false in onPause().






                                                                                                share|improve this answer















                                                                                                This is a very old question that came up on the sidebar for some reason.



                                                                                                If the background task only needs to survive while the activity is in the foreground, the "new" solution is to host the background thread (or, preferably, AsyncTask) in a retained fragment, as described in this developer guide and numerous Q&As.



                                                                                                A retained fragment survives if the activity is destroyed for a configuration change, but not when the activity is destroyed in the background or back stack. Therefore, the background task should still be interrupted if isChangingConfigurations() is false in onPause().







                                                                                                share|improve this answer














                                                                                                share|improve this answer



                                                                                                share|improve this answer








                                                                                                edited May 23 '17 at 12:03









                                                                                                Community

                                                                                                11




                                                                                                11










                                                                                                answered Jul 4 '16 at 6:02









                                                                                                Kevin KrumwiedeKevin Krumwiede

                                                                                                6,41131852




                                                                                                6,41131852























                                                                                                    1














                                                                                                    I am a fresher in android and I tried this and it's worked.



                                                                                                    public class loadTotalMemberByBranch extends AsyncTask<Void, Void,Void> {
                                                                                                    ProgressDialog progressDialog = new ProgressDialog(Login.this);
                                                                                                    int ranSucess=0;
                                                                                                    @Override
                                                                                                    protected void onPreExecute() {
                                                                                                    // TODO Auto-generated method stub
                                                                                                    super.onPreExecute();
                                                                                                    progressDialog.setTitle("");
                                                                                                    progressDialog.isIndeterminate();
                                                                                                    progressDialog.setCancelable(false);
                                                                                                    progressDialog.show();
                                                                                                    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR);

                                                                                                    }
                                                                                                    @Override
                                                                                                    protected Void doInBackground(Void... params) {
                                                                                                    // TODO Auto-generated method stub

                                                                                                    return null;
                                                                                                    }
                                                                                                    @Override
                                                                                                    protected void onPostExecute(Void result) {
                                                                                                    // TODO Auto-generated method stub
                                                                                                    super.onPostExecute(result);
                                                                                                    progressDialog.dismiss();
                                                                                                    setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR);
                                                                                                    }
                                                                                                    }





                                                                                                    share|improve this answer






























                                                                                                      1














                                                                                                      I am a fresher in android and I tried this and it's worked.



                                                                                                      public class loadTotalMemberByBranch extends AsyncTask<Void, Void,Void> {
                                                                                                      ProgressDialog progressDialog = new ProgressDialog(Login.this);
                                                                                                      int ranSucess=0;
                                                                                                      @Override
                                                                                                      protected void onPreExecute() {
                                                                                                      // TODO Auto-generated method stub
                                                                                                      super.onPreExecute();
                                                                                                      progressDialog.setTitle("");
                                                                                                      progressDialog.isIndeterminate();
                                                                                                      progressDialog.setCancelable(false);
                                                                                                      progressDialog.show();
                                                                                                      setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR);

                                                                                                      }
                                                                                                      @Override
                                                                                                      protected Void doInBackground(Void... params) {
                                                                                                      // TODO Auto-generated method stub

                                                                                                      return null;
                                                                                                      }
                                                                                                      @Override
                                                                                                      protected void onPostExecute(Void result) {
                                                                                                      // TODO Auto-generated method stub
                                                                                                      super.onPostExecute(result);
                                                                                                      progressDialog.dismiss();
                                                                                                      setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR);
                                                                                                      }
                                                                                                      }





                                                                                                      share|improve this answer




























                                                                                                        1












                                                                                                        1








                                                                                                        1







                                                                                                        I am a fresher in android and I tried this and it's worked.



                                                                                                        public class loadTotalMemberByBranch extends AsyncTask<Void, Void,Void> {
                                                                                                        ProgressDialog progressDialog = new ProgressDialog(Login.this);
                                                                                                        int ranSucess=0;
                                                                                                        @Override
                                                                                                        protected void onPreExecute() {
                                                                                                        // TODO Auto-generated method stub
                                                                                                        super.onPreExecute();
                                                                                                        progressDialog.setTitle("");
                                                                                                        progressDialog.isIndeterminate();
                                                                                                        progressDialog.setCancelable(false);
                                                                                                        progressDialog.show();
                                                                                                        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR);

                                                                                                        }
                                                                                                        @Override
                                                                                                        protected Void doInBackground(Void... params) {
                                                                                                        // TODO Auto-generated method stub

                                                                                                        return null;
                                                                                                        }
                                                                                                        @Override
                                                                                                        protected void onPostExecute(Void result) {
                                                                                                        // TODO Auto-generated method stub
                                                                                                        super.onPostExecute(result);
                                                                                                        progressDialog.dismiss();
                                                                                                        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR);
                                                                                                        }
                                                                                                        }





                                                                                                        share|improve this answer















                                                                                                        I am a fresher in android and I tried this and it's worked.



                                                                                                        public class loadTotalMemberByBranch extends AsyncTask<Void, Void,Void> {
                                                                                                        ProgressDialog progressDialog = new ProgressDialog(Login.this);
                                                                                                        int ranSucess=0;
                                                                                                        @Override
                                                                                                        protected void onPreExecute() {
                                                                                                        // TODO Auto-generated method stub
                                                                                                        super.onPreExecute();
                                                                                                        progressDialog.setTitle("");
                                                                                                        progressDialog.isIndeterminate();
                                                                                                        progressDialog.setCancelable(false);
                                                                                                        progressDialog.show();
                                                                                                        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR);

                                                                                                        }
                                                                                                        @Override
                                                                                                        protected Void doInBackground(Void... params) {
                                                                                                        // TODO Auto-generated method stub

                                                                                                        return null;
                                                                                                        }
                                                                                                        @Override
                                                                                                        protected void onPostExecute(Void result) {
                                                                                                        // TODO Auto-generated method stub
                                                                                                        super.onPostExecute(result);
                                                                                                        progressDialog.dismiss();
                                                                                                        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR);
                                                                                                        }
                                                                                                        }






                                                                                                        share|improve this answer














                                                                                                        share|improve this answer



                                                                                                        share|improve this answer








                                                                                                        edited Jul 6 '16 at 21:14









                                                                                                        ssuperczynski

                                                                                                        1,53112446




                                                                                                        1,53112446










                                                                                                        answered Jul 8 '15 at 11:44









                                                                                                        CloyCloy

                                                                                                        1,5211222




                                                                                                        1,5211222























                                                                                                            0














                                                                                                            Seems far too 'quick and dirty' to be true so please point out the flaws but what I found worked was...



                                                                                                            Within the onPostExecute method of my AsyncTask, I simply wrapped the '.dismiss' for the progress dialog in a try/catch block (with an empty catch) and then simply ignored the exception that was raised. Seems wrong to do but appears there are no ill effects (at least for what I am doing subsequently which is to start another activity passing in the result of my long running query as an Extra)






                                                                                                            share|improve this answer
























                                                                                                            • Are-you saying there is actually no memory leak when the Android platforms tells the window is leaked?

                                                                                                              – rds
                                                                                                              Mar 10 '11 at 18:09











                                                                                                            • My progress dialog is a member variable of the activity class so I assumed that when the activity is destroyed and recreated it will be garbage collected and there is no leak. Am I wrong?

                                                                                                              – Simon
                                                                                                              Mar 28 '11 at 20:01











                                                                                                            • Yes, I think it's wrong. As you say, the Activity has a reference to the Dialog. When the configuration is changed, the first Activity is destroyed, which means all fields are set to null. But the low-level WindowManager also has a reference to the Dialog (since it is has not been dismissed yet). The new Activity tries to create a new Dialog (in preExecute()) and the window manager raises a fatal exception preventing you from doing so. Indeed, if it does so, there would be no way to cleanly destroy the Dialog hence keeping a reference to the initial Activity. Am I right?

                                                                                                              – rds
                                                                                                              Mar 29 '11 at 21:20
















                                                                                                            0














                                                                                                            Seems far too 'quick and dirty' to be true so please point out the flaws but what I found worked was...



                                                                                                            Within the onPostExecute method of my AsyncTask, I simply wrapped the '.dismiss' for the progress dialog in a try/catch block (with an empty catch) and then simply ignored the exception that was raised. Seems wrong to do but appears there are no ill effects (at least for what I am doing subsequently which is to start another activity passing in the result of my long running query as an Extra)






                                                                                                            share|improve this answer
























                                                                                                            • Are-you saying there is actually no memory leak when the Android platforms tells the window is leaked?

                                                                                                              – rds
                                                                                                              Mar 10 '11 at 18:09











                                                                                                            • My progress dialog is a member variable of the activity class so I assumed that when the activity is destroyed and recreated it will be garbage collected and there is no leak. Am I wrong?

                                                                                                              – Simon
                                                                                                              Mar 28 '11 at 20:01











                                                                                                            • Yes, I think it's wrong. As you say, the Activity has a reference to the Dialog. When the configuration is changed, the first Activity is destroyed, which means all fields are set to null. But the low-level WindowManager also has a reference to the Dialog (since it is has not been dismissed yet). The new Activity tries to create a new Dialog (in preExecute()) and the window manager raises a fatal exception preventing you from doing so. Indeed, if it does so, there would be no way to cleanly destroy the Dialog hence keeping a reference to the initial Activity. Am I right?

                                                                                                              – rds
                                                                                                              Mar 29 '11 at 21:20














                                                                                                            0












                                                                                                            0








                                                                                                            0







                                                                                                            Seems far too 'quick and dirty' to be true so please point out the flaws but what I found worked was...



                                                                                                            Within the onPostExecute method of my AsyncTask, I simply wrapped the '.dismiss' for the progress dialog in a try/catch block (with an empty catch) and then simply ignored the exception that was raised. Seems wrong to do but appears there are no ill effects (at least for what I am doing subsequently which is to start another activity passing in the result of my long running query as an Extra)






                                                                                                            share|improve this answer













                                                                                                            Seems far too 'quick and dirty' to be true so please point out the flaws but what I found worked was...



                                                                                                            Within the onPostExecute method of my AsyncTask, I simply wrapped the '.dismiss' for the progress dialog in a try/catch block (with an empty catch) and then simply ignored the exception that was raised. Seems wrong to do but appears there are no ill effects (at least for what I am doing subsequently which is to start another activity passing in the result of my long running query as an Extra)







                                                                                                            share|improve this answer












                                                                                                            share|improve this answer



                                                                                                            share|improve this answer










                                                                                                            answered Nov 10 '10 at 10:58









                                                                                                            SimonSimon

                                                                                                            411




                                                                                                            411













                                                                                                            • Are-you saying there is actually no memory leak when the Android platforms tells the window is leaked?

                                                                                                              – rds
                                                                                                              Mar 10 '11 at 18:09











                                                                                                            • My progress dialog is a member variable of the activity class so I assumed that when the activity is destroyed and recreated it will be garbage collected and there is no leak. Am I wrong?

                                                                                                              – Simon
                                                                                                              Mar 28 '11 at 20:01











                                                                                                            • Yes, I think it's wrong. As you say, the Activity has a reference to the Dialog. When the configuration is changed, the first Activity is destroyed, which means all fields are set to null. But the low-level WindowManager also has a reference to the Dialog (since it is has not been dismissed yet). The new Activity tries to create a new Dialog (in preExecute()) and the window manager raises a fatal exception preventing you from doing so. Indeed, if it does so, there would be no way to cleanly destroy the Dialog hence keeping a reference to the initial Activity. Am I right?

                                                                                                              – rds
                                                                                                              Mar 29 '11 at 21:20



















                                                                                                            • Are-you saying there is actually no memory leak when the Android platforms tells the window is leaked?

                                                                                                              – rds
                                                                                                              Mar 10 '11 at 18:09











                                                                                                            • My progress dialog is a member variable of the activity class so I assumed that when the activity is destroyed and recreated it will be garbage collected and there is no leak. Am I wrong?

                                                                                                              – Simon
                                                                                                              Mar 28 '11 at 20:01











                                                                                                            • Yes, I think it's wrong. As you say, the Activity has a reference to the Dialog. When the configuration is changed, the first Activity is destroyed, which means all fields are set to null. But the low-level WindowManager also has a reference to the Dialog (since it is has not been dismissed yet). The new Activity tries to create a new Dialog (in preExecute()) and the window manager raises a fatal exception preventing you from doing so. Indeed, if it does so, there would be no way to cleanly destroy the Dialog hence keeping a reference to the initial Activity. Am I right?

                                                                                                              – rds
                                                                                                              Mar 29 '11 at 21:20

















                                                                                                            Are-you saying there is actually no memory leak when the Android platforms tells the window is leaked?

                                                                                                            – rds
                                                                                                            Mar 10 '11 at 18:09





                                                                                                            Are-you saying there is actually no memory leak when the Android platforms tells the window is leaked?

                                                                                                            – rds
                                                                                                            Mar 10 '11 at 18:09













                                                                                                            My progress dialog is a member variable of the activity class so I assumed that when the activity is destroyed and recreated it will be garbage collected and there is no leak. Am I wrong?

                                                                                                            – Simon
                                                                                                            Mar 28 '11 at 20:01





                                                                                                            My progress dialog is a member variable of the activity class so I assumed that when the activity is destroyed and recreated it will be garbage collected and there is no leak. Am I wrong?

                                                                                                            – Simon
                                                                                                            Mar 28 '11 at 20:01













                                                                                                            Yes, I think it's wrong. As you say, the Activity has a reference to the Dialog. When the configuration is changed, the first Activity is destroyed, which means all fields are set to null. But the low-level WindowManager also has a reference to the Dialog (since it is has not been dismissed yet). The new Activity tries to create a new Dialog (in preExecute()) and the window manager raises a fatal exception preventing you from doing so. Indeed, if it does so, there would be no way to cleanly destroy the Dialog hence keeping a reference to the initial Activity. Am I right?

                                                                                                            – rds
                                                                                                            Mar 29 '11 at 21:20





                                                                                                            Yes, I think it's wrong. As you say, the Activity has a reference to the Dialog. When the configuration is changed, the first Activity is destroyed, which means all fields are set to null. But the low-level WindowManager also has a reference to the Dialog (since it is has not been dismissed yet). The new Activity tries to create a new Dialog (in preExecute()) and the window manager raises a fatal exception preventing you from doing so. Indeed, if it does so, there would be no way to cleanly destroy the Dialog hence keeping a reference to the initial Activity. Am I right?

                                                                                                            – rds
                                                                                                            Mar 29 '11 at 21:20











                                                                                                            0














                                                                                                            The simplest and most flexible solution is to use an AsyncTask with a static reference to ProgressBar. This provides an encapsulated and thus reusable solution to orientation change problems. This solution has served me well for varying asyncronous tasks including internet downloads, communicating with Services, and filesystem scans. The solution has been well tested on multiple android versions and phone models. A complete demo can be found here with specific interest in DownloadFile.java



                                                                                                            I present the following as a concept example



                                                                                                            public class SimpleAsync extends AsyncTask<String, Integer, String> {
                                                                                                            private static ProgressDialog mProgressDialog = null;
                                                                                                            private final Context mContext;

                                                                                                            public SimpleAsync(Context context) {
                                                                                                            mContext = context;
                                                                                                            if ( mProgressDialog != null ) {
                                                                                                            onPreExecute();
                                                                                                            }
                                                                                                            }

                                                                                                            @Override
                                                                                                            protected void onPreExecute() {
                                                                                                            mProgressDialog = new ProgressDialog( mContext );
                                                                                                            mProgressDialog.show();
                                                                                                            }

                                                                                                            @Override
                                                                                                            protected void onPostExecute(String result) {
                                                                                                            if ( mProgressDialog != null ) {
                                                                                                            mProgressDialog.dismiss();
                                                                                                            mProgressDialog = null;
                                                                                                            }
                                                                                                            }

                                                                                                            @Override
                                                                                                            protected void onProgressUpdate(Integer... progress) {
                                                                                                            mProgressDialog.setProgress( progress[0] );
                                                                                                            }

                                                                                                            @Override
                                                                                                            protected String doInBackground(String... sUrl) {
                                                                                                            // Do some work here
                                                                                                            publishProgress(1);
                                                                                                            return null;
                                                                                                            }

                                                                                                            public void dismiss() {
                                                                                                            if ( mProgressDialog != null ) {
                                                                                                            mProgressDialog.dismiss();
                                                                                                            }
                                                                                                            }
                                                                                                            }


                                                                                                            Usage in an Android Activity is simple



                                                                                                            public class MainActivity extends Activity {
                                                                                                            DemoServiceClient mClient = null;
                                                                                                            DownloadFile mDownloadFile = null;

                                                                                                            @Override
                                                                                                            public void onCreate(Bundle savedInstanceState) {
                                                                                                            super.onCreate( savedInstanceState );
                                                                                                            setContentView( R.layout.main );
                                                                                                            mDownloadFile = new DownloadFile( this );

                                                                                                            Button downloadButton = (Button) findViewById( R.id.download_file_button );
                                                                                                            downloadButton.setOnClickListener( new View.OnClickListener() {
                                                                                                            @Override
                                                                                                            public void onClick(View view) {
                                                                                                            mDownloadFile.execute( "http://www.textfiles.com/food/bakebred.txt");
                                                                                                            }
                                                                                                            });
                                                                                                            }

                                                                                                            @Override
                                                                                                            public void onPause() {
                                                                                                            super.onPause();
                                                                                                            mDownloadFile.dismiss();
                                                                                                            }
                                                                                                            }





                                                                                                            share|improve this answer




























                                                                                                              0














                                                                                                              The simplest and most flexible solution is to use an AsyncTask with a static reference to ProgressBar. This provides an encapsulated and thus reusable solution to orientation change problems. This solution has served me well for varying asyncronous tasks including internet downloads, communicating with Services, and filesystem scans. The solution has been well tested on multiple android versions and phone models. A complete demo can be found here with specific interest in DownloadFile.java



                                                                                                              I present the following as a concept example



                                                                                                              public class SimpleAsync extends AsyncTask<String, Integer, String> {
                                                                                                              private static ProgressDialog mProgressDialog = null;
                                                                                                              private final Context mContext;

                                                                                                              public SimpleAsync(Context context) {
                                                                                                              mContext = context;
                                                                                                              if ( mProgressDialog != null ) {
                                                                                                              onPreExecute();
                                                                                                              }
                                                                                                              }

                                                                                                              @Override
                                                                                                              protected void onPreExecute() {
                                                                                                              mProgressDialog = new ProgressDialog( mContext );
                                                                                                              mProgressDialog.show();
                                                                                                              }

                                                                                                              @Override
                                                                                                              protected void onPostExecute(String result) {
                                                                                                              if ( mProgressDialog != null ) {
                                                                                                              mProgressDialog.dismiss();
                                                                                                              mProgressDialog = null;
                                                                                                              }
                                                                                                              }

                                                                                                              @Override
                                                                                                              protected void onProgressUpdate(Integer... progress) {
                                                                                                              mProgressDialog.setProgress( progress[0] );
                                                                                                              }

                                                                                                              @Override
                                                                                                              protected String doInBackground(String... sUrl) {
                                                                                                              // Do some work here
                                                                                                              publishProgress(1);
                                                                                                              return null;
                                                                                                              }

                                                                                                              public void dismiss() {
                                                                                                              if ( mProgressDialog != null ) {
                                                                                                              mProgressDialog.dismiss();
                                                                                                              }
                                                                                                              }
                                                                                                              }


                                                                                                              Usage in an Android Activity is simple



                                                                                                              public class MainActivity extends Activity {
                                                                                                              DemoServiceClient mClient = null;
                                                                                                              DownloadFile mDownloadFile = null;

                                                                                                              @Override
                                                                                                              public void onCreate(Bundle savedInstanceState) {
                                                                                                              super.onCreate( savedInstanceState );
                                                                                                              setContentView( R.layout.main );
                                                                                                              mDownloadFile = new DownloadFile( this );

                                                                                                              Button downloadButton = (Button) findViewById( R.id.download_file_button );
                                                                                                              downloadButton.setOnClickListener( new View.OnClickListener() {
                                                                                                              @Override
                                                                                                              public void onClick(View view) {
                                                                                                              mDownloadFile.execute( "http://www.textfiles.com/food/bakebred.txt");
                                                                                                              }
                                                                                                              });
                                                                                                              }

                                                                                                              @Override
                                                                                                              public void onPause() {
                                                                                                              super.onPause();
                                                                                                              mDownloadFile.dismiss();
                                                                                                              }
                                                                                                              }





                                                                                                              share|improve this answer


























                                                                                                                0












                                                                                                                0








                                                                                                                0







                                                                                                                The simplest and most flexible solution is to use an AsyncTask with a static reference to ProgressBar. This provides an encapsulated and thus reusable solution to orientation change problems. This solution has served me well for varying asyncronous tasks including internet downloads, communicating with Services, and filesystem scans. The solution has been well tested on multiple android versions and phone models. A complete demo can be found here with specific interest in DownloadFile.java



                                                                                                                I present the following as a concept example



                                                                                                                public class SimpleAsync extends AsyncTask<String, Integer, String> {
                                                                                                                private static ProgressDialog mProgressDialog = null;
                                                                                                                private final Context mContext;

                                                                                                                public SimpleAsync(Context context) {
                                                                                                                mContext = context;
                                                                                                                if ( mProgressDialog != null ) {
                                                                                                                onPreExecute();
                                                                                                                }
                                                                                                                }

                                                                                                                @Override
                                                                                                                protected void onPreExecute() {
                                                                                                                mProgressDialog = new ProgressDialog( mContext );
                                                                                                                mProgressDialog.show();
                                                                                                                }

                                                                                                                @Override
                                                                                                                protected void onPostExecute(String result) {
                                                                                                                if ( mProgressDialog != null ) {
                                                                                                                mProgressDialog.dismiss();
                                                                                                                mProgressDialog = null;
                                                                                                                }
                                                                                                                }

                                                                                                                @Override
                                                                                                                protected void onProgressUpdate(Integer... progress) {
                                                                                                                mProgressDialog.setProgress( progress[0] );
                                                                                                                }

                                                                                                                @Override
                                                                                                                protected String doInBackground(String... sUrl) {
                                                                                                                // Do some work here
                                                                                                                publishProgress(1);
                                                                                                                return null;
                                                                                                                }

                                                                                                                public void dismiss() {
                                                                                                                if ( mProgressDialog != null ) {
                                                                                                                mProgressDialog.dismiss();
                                                                                                                }
                                                                                                                }
                                                                                                                }


                                                                                                                Usage in an Android Activity is simple



                                                                                                                public class MainActivity extends Activity {
                                                                                                                DemoServiceClient mClient = null;
                                                                                                                DownloadFile mDownloadFile = null;

                                                                                                                @Override
                                                                                                                public void onCreate(Bundle savedInstanceState) {
                                                                                                                super.onCreate( savedInstanceState );
                                                                                                                setContentView( R.layout.main );
                                                                                                                mDownloadFile = new DownloadFile( this );

                                                                                                                Button downloadButton = (Button) findViewById( R.id.download_file_button );
                                                                                                                downloadButton.setOnClickListener( new View.OnClickListener() {
                                                                                                                @Override
                                                                                                                public void onClick(View view) {
                                                                                                                mDownloadFile.execute( "http://www.textfiles.com/food/bakebred.txt");
                                                                                                                }
                                                                                                                });
                                                                                                                }

                                                                                                                @Override
                                                                                                                public void onPause() {
                                                                                                                super.onPause();
                                                                                                                mDownloadFile.dismiss();
                                                                                                                }
                                                                                                                }





                                                                                                                share|improve this answer













                                                                                                                The simplest and most flexible solution is to use an AsyncTask with a static reference to ProgressBar. This provides an encapsulated and thus reusable solution to orientation change problems. This solution has served me well for varying asyncronous tasks including internet downloads, communicating with Services, and filesystem scans. The solution has been well tested on multiple android versions and phone models. A complete demo can be found here with specific interest in DownloadFile.java



                                                                                                                I present the following as a concept example



                                                                                                                public class SimpleAsync extends AsyncTask<String, Integer, String> {
                                                                                                                private static ProgressDialog mProgressDialog = null;
                                                                                                                private final Context mContext;

                                                                                                                public SimpleAsync(Context context) {
                                                                                                                mContext = context;
                                                                                                                if ( mProgressDialog != null ) {
                                                                                                                onPreExecute();
                                                                                                                }
                                                                                                                }

                                                                                                                @Override
                                                                                                                protected void onPreExecute() {
                                                                                                                mProgressDialog = new ProgressDialog( mContext );
                                                                                                                mProgressDialog.show();
                                                                                                                }

                                                                                                                @Override
                                                                                                                protected void onPostExecute(String result) {
                                                                                                                if ( mProgressDialog != null ) {
                                                                                                                mProgressDialog.dismiss();
                                                                                                                mProgressDialog = null;
                                                                                                                }
                                                                                                                }

                                                                                                                @Override
                                                                                                                protected void onProgressUpdate(Integer... progress) {
                                                                                                                mProgressDialog.setProgress( progress[0] );
                                                                                                                }

                                                                                                                @Override
                                                                                                                protected String doInBackground(String... sUrl) {
                                                                                                                // Do some work here
                                                                                                                publishProgress(1);
                                                                                                                return null;
                                                                                                                }

                                                                                                                public void dismiss() {
                                                                                                                if ( mProgressDialog != null ) {
                                                                                                                mProgressDialog.dismiss();
                                                                                                                }
                                                                                                                }
                                                                                                                }


                                                                                                                Usage in an Android Activity is simple



                                                                                                                public class MainActivity extends Activity {
                                                                                                                DemoServiceClient mClient = null;
                                                                                                                DownloadFile mDownloadFile = null;

                                                                                                                @Override
                                                                                                                public void onCreate(Bundle savedInstanceState) {
                                                                                                                super.onCreate( savedInstanceState );
                                                                                                                setContentView( R.layout.main );
                                                                                                                mDownloadFile = new DownloadFile( this );

                                                                                                                Button downloadButton = (Button) findViewById( R.id.download_file_button );
                                                                                                                downloadButton.setOnClickListener( new View.OnClickListener() {
                                                                                                                @Override
                                                                                                                public void onClick(View view) {
                                                                                                                mDownloadFile.execute( "http://www.textfiles.com/food/bakebred.txt");
                                                                                                                }
                                                                                                                });
                                                                                                                }

                                                                                                                @Override
                                                                                                                public void onPause() {
                                                                                                                super.onPause();
                                                                                                                mDownloadFile.dismiss();
                                                                                                                }
                                                                                                                }






                                                                                                                share|improve this answer












                                                                                                                share|improve this answer



                                                                                                                share|improve this answer










                                                                                                                answered May 10 '13 at 19:19









                                                                                                                Derrick J WipplerDerrick J Wippler

                                                                                                                1287




                                                                                                                1287























                                                                                                                    0














                                                                                                                    i have found and easier solution to handle threads when orientation change. You can just keep an static reference to your activity/fragment and verify if its null before acting on the ui. I suggest using a try catch too:



                                                                                                                     public class DashListFragment extends Fragment {
                                                                                                                    private static DashListFragment ACTIVE_INSTANCE;

                                                                                                                    @Override
                                                                                                                    public void onCreate(Bundle savedInstanceState) {
                                                                                                                    super.onCreate(savedInstanceState);

                                                                                                                    ACTIVE_INSTANCE = this;

                                                                                                                    new Handler().postDelayed(new Runnable() {
                                                                                                                    public void run() {
                                                                                                                    try {
                                                                                                                    if (ACTIVE_INSTANCE != null) {
                                                                                                                    setAdapter(); // this method do something on ui or use context
                                                                                                                    }
                                                                                                                    }
                                                                                                                    catch (Exception e) {}


                                                                                                                    }
                                                                                                                    }, 1500l);

                                                                                                                    }

                                                                                                                    @Override
                                                                                                                    public void onDestroy() {
                                                                                                                    super.onDestroy();

                                                                                                                    ACTIVE_INSTANCE = null;
                                                                                                                    }


                                                                                                                    }





                                                                                                                    share|improve this answer




























                                                                                                                      0














                                                                                                                      i have found and easier solution to handle threads when orientation change. You can just keep an static reference to your activity/fragment and verify if its null before acting on the ui. I suggest using a try catch too:



                                                                                                                       public class DashListFragment extends Fragment {
                                                                                                                      private static DashListFragment ACTIVE_INSTANCE;

                                                                                                                      @Override
                                                                                                                      public void onCreate(Bundle savedInstanceState) {
                                                                                                                      super.onCreate(savedInstanceState);

                                                                                                                      ACTIVE_INSTANCE = this;

                                                                                                                      new Handler().postDelayed(new Runnable() {
                                                                                                                      public void run() {
                                                                                                                      try {
                                                                                                                      if (ACTIVE_INSTANCE != null) {
                                                                                                                      setAdapter(); // this method do something on ui or use context
                                                                                                                      }
                                                                                                                      }
                                                                                                                      catch (Exception e) {}


                                                                                                                      }
                                                                                                                      }, 1500l);

                                                                                                                      }

                                                                                                                      @Override
                                                                                                                      public void onDestroy() {
                                                                                                                      super.onDestroy();

                                                                                                                      ACTIVE_INSTANCE = null;
                                                                                                                      }


                                                                                                                      }





                                                                                                                      share|improve this answer


























                                                                                                                        0












                                                                                                                        0








                                                                                                                        0







                                                                                                                        i have found and easier solution to handle threads when orientation change. You can just keep an static reference to your activity/fragment and verify if its null before acting on the ui. I suggest using a try catch too:



                                                                                                                         public class DashListFragment extends Fragment {
                                                                                                                        private static DashListFragment ACTIVE_INSTANCE;

                                                                                                                        @Override
                                                                                                                        public void onCreate(Bundle savedInstanceState) {
                                                                                                                        super.onCreate(savedInstanceState);

                                                                                                                        ACTIVE_INSTANCE = this;

                                                                                                                        new Handler().postDelayed(new Runnable() {
                                                                                                                        public void run() {
                                                                                                                        try {
                                                                                                                        if (ACTIVE_INSTANCE != null) {
                                                                                                                        setAdapter(); // this method do something on ui or use context
                                                                                                                        }
                                                                                                                        }
                                                                                                                        catch (Exception e) {}


                                                                                                                        }
                                                                                                                        }, 1500l);

                                                                                                                        }

                                                                                                                        @Override
                                                                                                                        public void onDestroy() {
                                                                                                                        super.onDestroy();

                                                                                                                        ACTIVE_INSTANCE = null;
                                                                                                                        }


                                                                                                                        }





                                                                                                                        share|improve this answer













                                                                                                                        i have found and easier solution to handle threads when orientation change. You can just keep an static reference to your activity/fragment and verify if its null before acting on the ui. I suggest using a try catch too:



                                                                                                                         public class DashListFragment extends Fragment {
                                                                                                                        private static DashListFragment ACTIVE_INSTANCE;

                                                                                                                        @Override
                                                                                                                        public void onCreate(Bundle savedInstanceState) {
                                                                                                                        super.onCreate(savedInstanceState);

                                                                                                                        ACTIVE_INSTANCE = this;

                                                                                                                        new Handler().postDelayed(new Runnable() {
                                                                                                                        public void run() {
                                                                                                                        try {
                                                                                                                        if (ACTIVE_INSTANCE != null) {
                                                                                                                        setAdapter(); // this method do something on ui or use context
                                                                                                                        }
                                                                                                                        }
                                                                                                                        catch (Exception e) {}


                                                                                                                        }
                                                                                                                        }, 1500l);

                                                                                                                        }

                                                                                                                        @Override
                                                                                                                        public void onDestroy() {
                                                                                                                        super.onDestroy();

                                                                                                                        ACTIVE_INSTANCE = null;
                                                                                                                        }


                                                                                                                        }






                                                                                                                        share|improve this answer












                                                                                                                        share|improve this answer



                                                                                                                        share|improve this answer










                                                                                                                        answered Oct 2 '15 at 15:11









                                                                                                                        sagitssagits

                                                                                                                        3,3042735




                                                                                                                        3,3042735























                                                                                                                            0














                                                                                                                            If you're struggling with detecting orientation change events of a dialog INDEPENDENT OF AN ACTIVITY REFERENCE, this method works excitingly well. I use this because I have my own dialog class that can be shown in multiple different Activities so I don't always know which Activity it's being shown in. With this method you don't need to change the AndroidManifest, worry about Activity references, and you don't need a custom dialog (as I have). You do need, however, a custom content view so you can detect the orientation changes using that particular view. Here's my example:



                                                                                                                            Setup



                                                                                                                            public class MyContentView extends View{
                                                                                                                            public MyContentView(Context context){
                                                                                                                            super(context);
                                                                                                                            }

                                                                                                                            @Override
                                                                                                                            public void onConfigurationChanged(Configuration newConfig){
                                                                                                                            super.onConfigurationChanged(newConfig);

                                                                                                                            //DO SOMETHING HERE!! :D
                                                                                                                            }
                                                                                                                            }


                                                                                                                            Implementation 1 - Dialog



                                                                                                                            Dialog dialog = new Dialog(context);
                                                                                                                            //set up dialog
                                                                                                                            dialog.setContentView(new MyContentView(context));
                                                                                                                            dialog.show();


                                                                                                                            Implementation 2 - AlertDialog.Builder



                                                                                                                            AlertDialog.Builder builder = new AlertDialog.Builder(context);
                                                                                                                            //set up dialog builder
                                                                                                                            builder.setView(new MyContentView(context)); //Can use this method
                                                                                                                            builder.setCustomTitle(new MycontentView(context)); // or this method
                                                                                                                            builder.build().show();


                                                                                                                            Implementation 3 - ProgressDialog / AlertDialog



                                                                                                                            ProgressDialog progress = new ProgressDialog(context);
                                                                                                                            //set up progress dialog
                                                                                                                            progress.setView(new MyContentView(context)); //Can use this method
                                                                                                                            progress.setCustomTitle(new MyContentView(context)); // or this method
                                                                                                                            progress.show();





                                                                                                                            share|improve this answer




























                                                                                                                              0














                                                                                                                              If you're struggling with detecting orientation change events of a dialog INDEPENDENT OF AN ACTIVITY REFERENCE, this method works excitingly well. I use this because I have my own dialog class that can be shown in multiple different Activities so I don't always know which Activity it's being shown in. With this method you don't need to change the AndroidManifest, worry about Activity references, and you don't need a custom dialog (as I have). You do need, however, a custom content view so you can detect the orientation changes using that particular view. Here's my example:



                                                                                                                              Setup



                                                                                                                              public class MyContentView extends View{
                                                                                                                              public MyContentView(Context context){
                                                                                                                              super(context);
                                                                                                                              }

                                                                                                                              @Override
                                                                                                                              public void onConfigurationChanged(Configuration newConfig){
                                                                                                                              super.onConfigurationChanged(newConfig);

                                                                                                                              //DO SOMETHING HERE!! :D
                                                                                                                              }
                                                                                                                              }


                                                                                                                              Implementation 1 - Dialog



                                                                                                                              Dialog dialog = new Dialog(context);
                                                                                                                              //set up dialog
                                                                                                                              dialog.setContentView(new MyContentView(context));
                                                                                                                              dialog.show();


                                                                                                                              Implementation 2 - AlertDialog.Builder



                                                                                                                              AlertDialog.Builder builder = new AlertDialog.Builder(context);
                                                                                                                              //set up dialog builder
                                                                                                                              builder.setView(new MyContentView(context)); //Can use this method
                                                                                                                              builder.setCustomTitle(new MycontentView(context)); // or this method
                                                                                                                              builder.build().show();


                                                                                                                              Implementation 3 - ProgressDialog / AlertDialog



                                                                                                                              ProgressDialog progress = new ProgressDialog(context);
                                                                                                                              //set up progress dialog
                                                                                                                              progress.setView(new MyContentView(context)); //Can use this method
                                                                                                                              progress.setCustomTitle(new MyContentView(context)); // or this method
                                                                                                                              progress.show();





                                                                                                                              share|improve this answer


























                                                                                                                                0












                                                                                                                                0








                                                                                                                                0







                                                                                                                                If you're struggling with detecting orientation change events of a dialog INDEPENDENT OF AN ACTIVITY REFERENCE, this method works excitingly well. I use this because I have my own dialog class that can be shown in multiple different Activities so I don't always know which Activity it's being shown in. With this method you don't need to change the AndroidManifest, worry about Activity references, and you don't need a custom dialog (as I have). You do need, however, a custom content view so you can detect the orientation changes using that particular view. Here's my example:



                                                                                                                                Setup



                                                                                                                                public class MyContentView extends View{
                                                                                                                                public MyContentView(Context context){
                                                                                                                                super(context);
                                                                                                                                }

                                                                                                                                @Override
                                                                                                                                public void onConfigurationChanged(Configuration newConfig){
                                                                                                                                super.onConfigurationChanged(newConfig);

                                                                                                                                //DO SOMETHING HERE!! :D
                                                                                                                                }
                                                                                                                                }


                                                                                                                                Implementation 1 - Dialog



                                                                                                                                Dialog dialog = new Dialog(context);
                                                                                                                                //set up dialog
                                                                                                                                dialog.setContentView(new MyContentView(context));
                                                                                                                                dialog.show();


                                                                                                                                Implementation 2 - AlertDialog.Builder



                                                                                                                                AlertDialog.Builder builder = new AlertDialog.Builder(context);
                                                                                                                                //set up dialog builder
                                                                                                                                builder.setView(new MyContentView(context)); //Can use this method
                                                                                                                                builder.setCustomTitle(new MycontentView(context)); // or this method
                                                                                                                                builder.build().show();


                                                                                                                                Implementation 3 - ProgressDialog / AlertDialog



                                                                                                                                ProgressDialog progress = new ProgressDialog(context);
                                                                                                                                //set up progress dialog
                                                                                                                                progress.setView(new MyContentView(context)); //Can use this method
                                                                                                                                progress.setCustomTitle(new MyContentView(context)); // or this method
                                                                                                                                progress.show();





                                                                                                                                share|improve this answer













                                                                                                                                If you're struggling with detecting orientation change events of a dialog INDEPENDENT OF AN ACTIVITY REFERENCE, this method works excitingly well. I use this because I have my own dialog class that can be shown in multiple different Activities so I don't always know which Activity it's being shown in. With this method you don't need to change the AndroidManifest, worry about Activity references, and you don't need a custom dialog (as I have). You do need, however, a custom content view so you can detect the orientation changes using that particular view. Here's my example:



                                                                                                                                Setup



                                                                                                                                public class MyContentView extends View{
                                                                                                                                public MyContentView(Context context){
                                                                                                                                super(context);
                                                                                                                                }

                                                                                                                                @Override
                                                                                                                                public void onConfigurationChanged(Configuration newConfig){
                                                                                                                                super.onConfigurationChanged(newConfig);

                                                                                                                                //DO SOMETHING HERE!! :D
                                                                                                                                }
                                                                                                                                }


                                                                                                                                Implementation 1 - Dialog



                                                                                                                                Dialog dialog = new Dialog(context);
                                                                                                                                //set up dialog
                                                                                                                                dialog.setContentView(new MyContentView(context));
                                                                                                                                dialog.show();


                                                                                                                                Implementation 2 - AlertDialog.Builder



                                                                                                                                AlertDialog.Builder builder = new AlertDialog.Builder(context);
                                                                                                                                //set up dialog builder
                                                                                                                                builder.setView(new MyContentView(context)); //Can use this method
                                                                                                                                builder.setCustomTitle(new MycontentView(context)); // or this method
                                                                                                                                builder.build().show();


                                                                                                                                Implementation 3 - ProgressDialog / AlertDialog



                                                                                                                                ProgressDialog progress = new ProgressDialog(context);
                                                                                                                                //set up progress dialog
                                                                                                                                progress.setView(new MyContentView(context)); //Can use this method
                                                                                                                                progress.setCustomTitle(new MyContentView(context)); // or this method
                                                                                                                                progress.show();






                                                                                                                                share|improve this answer












                                                                                                                                share|improve this answer



                                                                                                                                share|improve this answer










                                                                                                                                answered Nov 18 '15 at 18:13









                                                                                                                                kpninja12kpninja12

                                                                                                                                34149




                                                                                                                                34149

















                                                                                                                                    protected by Tim Post Feb 25 '11 at 11:04



                                                                                                                                    Thank you for your interest in this question.
                                                                                                                                    Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).



                                                                                                                                    Would you like to answer one of these unanswered questions instead?



                                                                                                                                    Popular posts from this blog

                                                                                                                                    How to send String Array data to Server using php in android

                                                                                                                                    Title Spacing in Bjornstrup Chapter, Removing Chapter Number From Contents

                                                                                                                                    Is anime1.com a legal site for watching anime?