【问题标题】:Executing two asynchronous tasks and updating AsyncTask message执行两个异步任务并更新 AsyncTask 消息
【发布时间】:2014-06-17 22:33:37
【问题描述】:

我有一段代码连接到服务器然后登录。在执行这两个任务(连接到服务器登录)时,一个进度对话框出现。

final ProgressDialog pd = new ProgressDialog(getActivity());
pd.setIndeterminate(true);
pd.setCancelable(false);

// While connecting to the server, the dialog should say the following:
pd.setTitle("Connecting...");
pd.setMessage("Connecting to " + hostname + "...");

pd.show();

new AsyncTask<Void, Void, Void>() {

    @Override
    protected Void doInBackground(Void... params) {
        try {

            // First task is executed. Progress dialog should say "Connecting..."
            executeTask1();

            // When the first task (connecting to server) is ready, I want the title
            // and the message of the progress dialog to be changed into this:
            pd.setTitle("Logging in"); //// MARKED LINE, see below. ////
            pd.setMessage("Trying to log in to server...");

            // Second task is executed.
            executeTask2();

            // Shows a screen and dismisses the ProgressDialog.
            showScreen(ScreenConstant.LIST_RESIDENTS);
            pd.dismiss();
        }
        catch (Exception exc) { }
    }
}

但是我遇到了两个问题:

  1. 执行 MARKED LINE(见上文)时会引发 RuntimeException:“只有创建视图层次结构的原始线程才能接触其视图”
  2. 登录任务从服务器获得响应,但该响应是异步的。

我希望ProgressDialog 在执行连接尝试时显示文本“正在连接...”。连接成功后,我希望将进度对话框的文本更改为“正在登录...”,同时正在执行登录尝试。

现在我应该如何做到这一点?

编辑

注意executeTask2() 触发一个任务在一个不同的线程中运行;它向服务器发送一个登录请求,因此我需要等到该线程准备好时向我发出信号。

【问题讨论】:

    标签: android android-asynctask progressdialog ui-thread


    【解决方案1】:

    任何涉及 UI 的代码都应该在主线程上完成,因此您需要使用 onProgressUpdate()publishProgress() 来促进这一点。

    例如:

    public void onProgressUpdate(Void... progress){
        super.onProgressUpdate(progress);
        pd.setTitle("Logging in");
        pd.setMessage("Trying to log in to server..."):
    }
    

    在您的doInBackground() 方法中:

    executeTask1();
    //task one finished, update UI
    publishProgress();
    

    除此之外,您应该在onPostExecute() 中关闭您的ProgressDialog,因为这也在主线程上执行

    【讨论】:

    • 感谢您的回答。但是,这只会解决我的问题中描述的问题#1。但是我怎样才能暂停线程的执行,等待服务器对我的登录请求的响应呢? (我可能需要Thread.join() 吗?)
    • 为什么不将代码从第二个任务 doInBackground() 移到第一个任务 doInBackground() 中?为此使用两个不同的 AsyncTask 似乎很浪费
    • 什么意思?我不使用两个不同的AsyncTasks,请参阅问题。
    • 您正在为 executeTask2() 使用不同的线程,为什么?在 doInBackground() 中执行时已经有一个后台线程,为什么还需要另一个?
    • 所以在库异步任务的成功/失败回调中关闭你的 ProgressDialog
    【解决方案2】:

    您需要在主线程中运行进度对话框,只有创建视图的线程才能更新或调用它,从而给您该异常。

    样本:

        @Override
        protected Void doInBackground(Void... params) {
            try {
    
                // First task is executed. Progress dialog should say "Connecting..."
                executeTask1();
    
                // When the first task (connecting to server) is ready, I want the title
                // and the message of the progress dialog to be changed into this:
                getActivity().runOnUiThread(new Runnable() {
    
                    @Override
                    public void run() {
                        pd.setTitle("Logging in"); //// MARKED LINE, see below. ////
                        pd.setMessage("Trying to log in to server...");
                    }
                });
    
    
                // Second task is executed.
                executeTask2();
    
                // Shows a screen and dismisses the ProgressDialog.
                showScreen(ScreenConstant.LIST_RESIDENTS);
    
                getActivity().runOnUiThread(new Runnable() {
    
                    @Override
                    public void run() {
                     pd.dismiss();  
    
    
                    }
                });
    
            }
            catch (Exception exc) { }
        }
    

    注意:

    明智的做法是关闭在主线程中运行的Asynctaskpost execute 方法中的对话框。

    【讨论】:

    • 谢谢。但这只会解决我的问题中描述的问题#1;问题 #2 仍未解决。 (请参阅@panini 答案下方的评论。)
    猜你喜欢
    • 2018-08-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-12
    • 1970-01-01
    相关资源
    最近更新 更多