我的程序在后台线程中执行一些网络活动.在开始之前,它会弹出一个进度对话框.处理程序上的对话框将被取消.这一切都很好,除了当对话框打开时屏幕方向改变时(背景线程正在运行).在这一点上,应用程序要么崩溃,要么死锁,或者进入一个奇怪的阶段,在所有线程都被杀死之前,应用程序根本不能工作.

如何优雅地处理屏幕方向的变化?

下面的示例代码与我的实际程序大致匹配:

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();
        }
    };
}

堆栈:

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)

我曾试图关闭onSaveInstanceState中的进度对话框,但这只会防止立即崩溃.后台线程仍在运行,UI处于部分绘制状态.需要在重新开始工作之前关闭整个应用程序.

推荐答案

当你切换方向时,Android将创建一个新视图.你可能会崩溃,因为你的后台线程正试图改变旧线程的状态.(它也可能有问题,因为你的后台线程不在UI线程上)

我建议将该mHandler设置为易失性,并在方向更改时对其进行更新.

Android相关问答推荐

道查询注释部分房间表名称

如何处理谷歌未经证实的应用程序拒绝?

懒惰的垂直网格中盒子的重量-Jetpack组合

即使安装了Chrome和YouTube,Android对action_view a YouTube URL的意图也是空的

合成-删除图像的部分背景

如何使用Jetpack Compose实现此底表?

如何显示具体的商品数量?

如何在 Jetpack Compose LazyColumn 中将项目分组在一起,例如卡片

更改当前活动并返回后,Android webview 滚动不起作用

任务 ':app:kaptGenerateStubsDebugKotlin' 执行失败

[Android][Room] 将密封类存储到 Room 数据库中

Android Studio 错误要求依赖它的库和应用程序针对 Android API 的 33 版或更高版本进行编译.

Kotlin 调用带参数的函数 Any is xxx ||任何 yyy 都不起作用

如何在 MAUI 项目中包含每个平台的现有 C++ 库?

Delphi 11:以编程方式查找 MSBuild 的正确工具版本

CenterAlignedTopAppBar 滚动行为:未为参数状态传递值

如何在 kotlin 的 android room DB 中设置一对多关系

如何在 flow.stateIn() 之后从流中的另一个函数发出emits ?

Android Java Keystore 在另一台机器上损坏

在 compose 屏幕之间传递 uri 会导致:SecurityException: Permission Denial