【问题标题】:It is possible to stop a thread until a dialog option has been chosed?在选择对话框选项之前可以停止线程吗?
【发布时间】:2015-02-27 12:10:51
【问题描述】:

众所周知,android 对话框只能在主 UI 线程下创建和显示。

问题是我有一个进度条,并且在一个线程中完成了很多工作,在进度的某些部分我必须显示一个对话框,并且用户必须选择一个选项才能继续工作。

所以.. 我需要在线程中显示一个对话框(阻塞线程直到用户选择了一个选项)。

我用这段代码试过了

public void showDialog(Activity activity) {
    Looper.prepare();
    AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(activity);

    // set title
    alertDialogBuilder.setTitle("");

    // set dialog message
    alertDialogBuilder
        .setMessage(R.string.STREAM_NOT_WIFI)
        .setCancelable(false)
        .setPositiveButton(R.string.STREAM_NOT_WIFI_YES, new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int id) {
                preload=true;
            }
        })
        .setNegativeButton(R.string.CANCEL, new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int id) {
                dialog.cancel();
                preload=false;
            }
        });

    // create alert dialog
    AlertDialog alertDialog = alertDialogBuilder.create();

    // show it
    alertDialog.show();
}

但我收到了这条消息,但没有显示对话框:

"attempting to initialize hardware acceleration outside of the main thread, aborting"

【问题讨论】:

    标签: android multithreading dialog android-dialog hardware-acceleration


    【解决方案1】:

    ActivityView 中有内置方法,您可以使用这些方法将任务从非 UI 线程发布到 UI 线程。其中之一是runOnUiThreadActivity

    示例:

    public class MainActivity extends Activity {
    
        @Override protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
    
            Thread thread = new Thread(new Runnable() {
    
                private final Object lock = new Object();
                private volatile boolean isEnabled = true;
    
                @Override public void run() {
    
                    while (isEnabled) {
                        try {
                            Log.e("sample", "working...");
                            Thread.sleep(5000);
                        } catch (InterruptedException e) {
                            //
                        }
    
    
                        runOnUiThread(new Runnable() {
                            @Override public void run() {
                                AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
                                builder.setPositiveButton("Continue", new DialogInterface.OnClickListener() {
                                    @Override public void onClick(DialogInterface dialog, int which) {
                                        synchronized (lock) {
                                            lock.notify();
                                        }
                                    }
                                });
                                builder.show();
                            }
                        });
    
                        synchronized (lock) {
                            try {
                                Log.e("sample", "work stopped. Waiting for dialog click.");
                                lock.wait();
                            } catch (InterruptedException e) {
                                //
                            }
                        }
    
                    }
    
                }
            });
            thread.start();
        }
    }
    

    示例看起来很乱,但它显示了从非 UI 线程运行任务的基础知识。 Activity 启动 Thread “工作” 5 秒,然后要求用户继续。当用户点击对话框的按钮时,线程继续执行工作。

    【讨论】:

    • 如果我使用 runonuithread 在 ui 线程上运行对话框,那么在用户按下按钮之前,对话框不会阻塞我的线程进程。线程正在继续
    • @AndroidUser99 您必须“手动”阻止您的线程。 Dialog 不能也不应该阻塞你的线程。请仔细阅读我的示例。
    • 我会尝试理解你的锁并在我的代码中添加阻塞逻辑,但我需要时间,代码很大
    • @AndroidUser99 如果我的回答帮助您以某种方式考虑投票或将其标记为答案。
    【解决方案2】:

    您不能简单地调用Looper.prepare() 并在UI 线程上显示任何线程。您需要后台线程与 UI 线程交互,这是有限制的。

    这是与此相关的一个很好的 SO 问题,但请务必阅读 3 或 4 个答案(不仅仅是第一个),并且问题本身与 Toast 有关 - 忽略它。你遇到的问题也差不多……

    Can't create handler inside thread that has not called Looper.prepare()

    此外,您可以在此处查看有关此类问题的教程:

    http://codetheory.in/android-handlers-runnables-loopers-messagequeue-handlerthread/

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-11-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-02-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多