Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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.

like image 386
Heikki Toivonen Avatar asked Jul 10 '09 21:07

Heikki Toivonen


People also ask

How can we cope with screen orientation changes?

If you want to manually handle orientation changes in your app you must declare the "orientation" , "screenSize" , and "screenLayout" values in the android:configChanges attributes. You can declare multiple configuration values in the attribute by separating them with a pipe | character.

How do I stop android from restarting activity when changing orientations?

If you want the activity to not restart during screen orientation change, you can use the below AndroidManifest. xml. Please note the activity android:configChanges=”orientation|screenSize” attribute. This attribute makes the activity not restart when change screen orientation.

How does the activity respond when the user rotates the screen?

When you rotate your device and the screen changes orientation, Android usually destroys your application's existing Activities and Fragments and recreates them. Android does this so that your application can reload resources based on the new configuration.

Which method is used to screen orientation?

from portrait => landscape mode).


2 Answers

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.

like image 98
sonxurxo Avatar answered Oct 09 '22 14:10

sonxurxo


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.

like image 21
haseman Avatar answered Oct 09 '22 16:10

haseman