使用AsyncTask(OnProgressDialog,Toasts)中的UI操作进行故障排除

时间:2013-12-26 19:03:23

标签: java android multithreading android-asynctask

我试图在AsyncTask中显示ProgressDialog,但我收到错误Can't create handler inside thread that has not called Looper.prepare()。 所以我搜索了它,发现here之前有人遇到过这个问题。

我接受了你在那里看到的第二个答案并以这种方式实现了我的AsyncTask。现在一切都很好,但我想必须有一些更好的方式来显示该对话框。

这是我修复后的AsyncTask

private class MyAsyncTask extends AsyncTask<Void, Void, ArrayList</*SomeObject*/>> {
    ProgressDialog mDialog;

    private MyAsyncTask() {
        getActivity().runOnUiThread(new Runnable() {
            public void run() {
                mDialog = new ProgressDialog(getActivity());
            }
        });
    }

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        getActivity().runOnUiThread(new Runnable() {
            @Override
            public void run() {
                mDialog.setMessage("AsyncTask is starting...");
                mDialog.show();
            }
        });
    }

    @Override
    protected ArrayList</*SomeObject*/> doInBackground(Void... params) {
        // some non UI related code...
    }

    @Override
    protected void onPostExecute(ArrayList</*SomeObject*/> someObjects) {
        super.onPostExecute(exams);
        // some code...
        getActivity().runOnUiThread(new Runnable() {
            @Override
            public void run() {
                mDialog.dismiss();
            }
        });
    }
}

我的问题是

  1. 有没有更好的方式来显示对话框?

  2. 为什么我只在这个特定的AsyncTask中得到错误? (以下代码效果很好)

  3. 我运行AsyncTask你可以在下面看到一百次并且它从未崩溃,而第一个从未成功执行过。肯定有一些我看不到的东西!

    private class MyAsyncTask extends AsyncTask<String, Void, String> {
        private final ProgressDialog dialog = new ProgressDialog(mContext);
    
        private LoginConnectTask() {
        }
    
        protected void onPreExecute() {
            super.onPreExecute();
            dialog.setMessage("aMessage");
            dialog.show();
        }
    
        protected String doInBackground(String... strings) {
            return fancyFunction(strings[0], strings[1]);
        }
    
        protected void onPostExecute(String s) {
            super.onPostExecute(s);
            if (s != null) {
                Toast.makeText(mContext, s, Toast.LENGTH_LONG).show();
            }
            dialog.dismiss();
        }
    }
    

1 个答案:

答案 0 :(得分:2)

AsyncTask以外的所有doInBackground()方法都在UI Thread上运行。因此,没有理由或想要在runOnUiThread()内部使用AsyncTask,这通常会导致问题(从我所看到的)。

因此,在构造函数中不需要它,并且在这种情况下似乎根本不需要构造函数。此外,在onPreExecute()中,您可以显示Dialog,因为它在UI Thread上运行。同样在onPostExecute()中解雇它。

所以直接回答你的问题,

  

有更好的方法来显示对话框吗?

不,你在第二位代码中这样做的方式非常精细且正常

  

为什么我只在这个特定的AsyncTask中得到错误? (以下代码效果很好)

确定没有看到所有代码的确切原因,但正如Raghunandan所说,“当你从非ui线程更新ui时通常会发生错误”但是,如上所述,没有理由使用runOnUiThread()AsyncTask内。在大多数情况下,至少没有理由我知道也没有理由。