android - 如何控制屏幕方向的变化?
ringa_lee
ringa_lee 2017-04-17 11:25:28
0
1
698

我的程序主要是控制后台线程的一些network activity,在启动之前,突然弹出了一个进度对话框,这个对话框是处理器上被驳回的。而当后台线程都运行的时候,对话框会弹出,此时,只要改变屏幕的方向,系统中的应用要么崩溃,要么死机,要么完全处于一种奇怪的运行状态中(平时只会出现在取消线程的情况中)。
我怎样才能成功的改变屏幕的方向?
下述代码可以大致描述程序运行的方式:

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)
E/WindowManager(  244):     at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:857)
E/WindowManager(  244):     at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:857)
E/WindowManager(  244):     at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:857)
E/WindowManager(  244):     at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:857)
E/WindowManager(  244):     at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:857)
E/WindowManager(  244):     at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:1593)
E/WindowManager(  244):     at com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1089)
E/WindowManager(  244):     at android.app.Activity.dispatchTouchEvent(Activity.java:1871)
E/WindowManager(  244):     at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:1577)
E/WindowManager(  244):     at android.view.ViewRoot.handleMessage(ViewRoot.java:1140)
E/WindowManager(  244):     at android.os.Handler.dispatchMessage(Handler.java:88)
E/WindowManager(  244):     at android.os.Looper.loop(Looper.java:123)
E/WindowManager(  244):     at android.app.ActivityThread.main(ActivityThread.java:3739)
E/WindowManager(  244):     at java.lang.reflect.Method.invokeNative(Native Method)
E/WindowManager(  244):     at java.lang.reflect.Method.invoke(Method.java:515)
E/WindowManager(  244):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:739)
E/WindowManager(  244):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:497)

以及:

W/dalvikvm( 244): threadid=3: thread exiting with uncaught exception (group=0x4000fe68)

E/AndroidRuntime( 244): Uncaught handler: thread main exiting due to uncaught exception

E/AndroidRuntime( 244): java.lang.IllegalArgumentException: View not attached to window manager

E/AndroidRuntime( 244):   at android.view.WindowManagerImpl.findViewLocked(WindowManagerImpl.java:331)

E/AndroidRuntime( 244):   at android.view.WindowManagerImpl.removeView(WindowManagerImpl.java:200)

E/AndroidRuntime( 244):   at android.view.Window$LocalWindowManager.removeView(Window.java:401)

E/AndroidRuntime( 244):   at android.app.Dialog.dismissDialog(Dialog.java:249)

E/AndroidRuntime( 244):   at android.app.Dialog.access$000(Dialog.java:59)

E/AndroidRuntime( 244):   at android.app.Dialog$1.run(Dialog.java:93)

E/AndroidRuntime( 244):   at android.app.Dialog.dismiss(Dialog.java:233)

E/AndroidRuntime( 244):   at MyAct$1.handleMessage(MyAct.java:321)

E/AndroidRuntime( 244):   at android.os.Handler.dispatchMessage(Handler.java:88)

E/AndroidRuntime( 244):   at android.os.Looper.loop(Looper.java:123)

E/AndroidRuntime( 244):   at android.app.ActivityThread.main(ActivityThread.java:3739)

E/AndroidRuntime( 244):   at java.lang.reflect.Method.invokeNative(Native Method)

E/AndroidRuntime( 244):   at java.lang.reflect.Method.invoke(Method.java:515)

E/AndroidRuntime( 244):   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:739)

E/AndroidRuntime( 244):   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:497)

E/AndroidRuntime( 244):   at dalvik.system.NativeStart.main(Native Method)

I/Process (  46): Sending signal. PID: 244 SIG: 3

I/dalvikvm( 244): threadid=7: reacting to signal 3

I/dalvikvm( 244): Wrote stack trace to '/data/anr/traces.txt'

I/Process ( 244): Sending signal. PID: 244 SIG: 9

I/ActivityManager(  46): Process MyAct (pid 244) has died.

我试图在onSaveInstanceState上取消对话框的进度条,但是这只能防止立即崩溃。后台线程仍然在运行,而且这个用户界面有一部分是处于拉伸状态的,需要杀掉整个应用程序才会重新开始工作。遇到这种情况,该怎么处理呢?

原问题:How to handle screen orientation change when progress dialog and background thread active?

ringa_lee
ringa_lee

ringa_lee

répondre à tous(1)
小葫芦

答:haseman
(最佳答案)
当你转换方向的时候,Android将会创建一个新的视图(View)。你的程序可能会崩溃,因为你的后台线程是试图在一个旧的视图上改变这个场景。(它可能也会有问题,因为你的后台的线程不是在UI的线程上)
我建议当方向改变的时候改变处理器并且进行更新。


答:sonxurxo
你需要添加下述代码加到控件的声明(declaration)中

android:configChanges="orientation"

就像这样

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

当配置发生改变的时候,系统破坏了这个控件就出现了问题。所以把上述代码放在配置文件中就可以避免系统破坏你的控件。


答: Pzanno
我遇到了同样的问题,并且想到了一个解决方案,不涉及使用ProgressDialog,而且可以更快的得到了结果。
我所做的就是创建一个内置ProgressBar的layout,具体方法如下:

<?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>

然后在onCreate中执行以下操作

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

然后在线程里做任务,当任务完成后是一个可运行的状态时,你就可以把目录视图(content view)加入到预期的layout中。
例如:

mHandler.post(new Runnable(){

public void run() {
        setContentView(R.layout.my_layout);
    } 
});
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal