【问题标题】:Android runOnUiThread explanationAndroid runOnUiThread 解释
【发布时间】:2012-06-29 00:01:56
【问题描述】:

我试图在我的一个活动的 onCreate() 方法期间显示进度对话框,在线程中完成填充屏幕的工作,然后关闭进度对话框。

这是我的 onCreateMethod()

dialog = new ProgressDialog(HeadlineBoard.this);
        dialog.setMessage("Populating Headlines.....");
        dialog.show();
        populateTable();

populateTable 方法包含我的线程和关闭对话框的代码,但出于某种原因。活动出现空白大约 10 秒(执行 populateTable() 工作),然后我看到屏幕。我从来没有看到显示的对话框,有什么想法吗?

这里是 populateTable() 代码:

//Adds a row to the table for each headline passed in
private void populateTable() {
    new Thread() {
        @Override
        public void run() {
            //If there are stories, add them to the table
            for (Parcelable currentHeadline : allHeadlines) {
                addHeadlineToTable(currentHeadline);
            }
               try {
                     // code runs in a thread
                     runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                dialog.dismiss();
                            }
                     });
               } catch (final Exception ex) {
                   Log.i("---","Exception in thread");
               }
        }
 }.start();

}

【问题讨论】:

  • If there are stories, add them to the table。您在 UI 线程上运行此代码,而不是在您创建的线程上。
  • 不确定您的建议是什么?
  • 将runOnUiThread中的所有代码移出到void run(),只留下dialog.dismiss();
  • 这给了我“只有创建视图的原始线程......”例外。
  • 或者我没有做出正确的改变?

标签: android


【解决方案1】:

如果您已经拥有“for (Parcelable currentHeadline : allHeadlines)”的数据,那么为什么要在单独的线程中执行此操作?

您应该在单独的线程中轮询数据,并在完成收集数据后,在 UI 线程上调用您的 populateTables 方法:

private void populateTable() {
    runOnUiThread(new Runnable(){
        public void run() {
            //If there are stories, add them to the table
            for (Parcelable currentHeadline : allHeadlines) {
                addHeadlineToTable(currentHeadline);
            }
            try {
                dialog.dismiss();
            } catch (final Exception ex) {
                Log.i("---","Exception in thread");
            }
        }
    });
}

【讨论】:

  • 我试过了,它运行时没有抛出异常,但我仍然没有看到对话框,它只是空白,然后在屏幕构建后显示活动。
  • 那你做错了。您是否在 UI 线程中创建对话框?为什么要使用 HeadLineBoard.this?为什么不是你的上下文?
【解决方案2】:

这应该适合你

 public class MyActivity extends Activity {

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

    private void populateTable() {
        mProgressDialog = ProgressDialog.show(this, "Please wait","Long operation starts...", true);
        new Thread() {
            @Override
            public void run() {

                doLongOperation();
                try {

                    // code runs in a thread
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            mProgressDialog.dismiss();
                        }
                    });
                } catch (final Exception ex) {
                    Log.i("---","Exception in thread");
                }
            }
        }.start();

    }

    /** fake operation for testing purpose */
    protected void doLongOperation() {
        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
        }

    }
}

【讨论】:

  • hmm.. 仍然遇到漏窗问题。
  • 在你的解决方案中尝试在 for 循环之前添加 Thread.sleep(500) 看看你得到了什么!!,
  • 同样的行为。我在 Activity 的 onCreate() 方法中初始化了 ProgressDialog 和 show(),如果这很重要的话。
  • @user1154644 检查我更新的答案我已经做了一些测试,试图让你的代码适应它。如果您发现问题,请告诉我,如果它解决了您的问题,请不要忘记接受并支持答案
  • 仍然抛出leakedWindow问题,但那是因为longOperation更新了UI。
【解决方案3】:

不是创建线程,而是使用runOnUIThread,这是ASyncTask 的完美工作:

  • onPreExecute 中,创建并显示对话框。

  • doInBackground准备数据,但不要触碰用户界面——将每个准备好的数据存储在一个字段中,然后调用publishProgress

    李>
  • onProgressUpdate 中读取数据字段并对 UI 进行适当的更改/添加。

  • onPostExecute 中关闭对话框。


如果您有其他原因需要线程,或者正在向现有线程添加 UI 触摸逻辑,则执行与我描述的类似的技术,仅在 UI 线程上运行很短的时间,使用 runOnUIThread每个 UI 步骤。在这种情况下,您会将每个数据存储在本地 final 变量(或您的类的字段)中,然后在 runOnUIThread 块中使用它。

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-02-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-09-22
  • 2015-06-10
相关资源
最近更新 更多