【问题标题】:Wait for AsyncTask to finish等待 AsyncTask 完成
【发布时间】:2013-11-12 22:00:14
【问题描述】:

您好,我正在制作访问 MySQL 数据库的登录页面。但是我的Activity 总是在完成AsyncTask 之前运行检查失败/成功的代码。

我尝试使用asynctask.get() 方法,但它只是冻结了我的用户界面并且不起作用。

我试过这个answer 说我应该在onPostExecute() 中调用结果检查器方法。

但由于我需要更改 TextView 以显示成功/失败,它会导致 NullPointerException,因为我在 onCreate() 中实例化了 TextView。

我无法将 TextView 实例化移动到构造函数中,因为它将返回 NullPointerException unable to instantiate activity ComponentInfo

Login.java

public class Login extends Activity{

    //declare global Views here

    protected void onCreate(Bundle bundle){
        //Setup views
    }

    protected void onClick(View v){
        //Setup necessary variables
        AsyncClass async = new AsyncClass(this);
        async.execute(username, password);
    }

    public void checkSuccess(boolean success){
        if(success)
            textView1.setText("Success");
        else
            textView1.setText("Failed");
    }
}

AsyncClass.java

public class AsyncClass extends AsyncTask<String, String, JSONObject>{
    protected JSONObject doInBackground(String... params){
        //access database
    }

    protected void onPostExecute(JSONObject json){
        //read the json result
        Login login = new Login();
        login.checkSuccess(true);
    }
}

有什么解决办法吗?谢谢

【问题讨论】:

  • 您的代码最明显的问题是您直接调用Activity 的构造函数。你不应该自己实例化Activity,请查看Activity lifecycle
  • @dave.c 感谢您的提示。

标签: android android-asynctask


【解决方案1】:

把 AsyncTask 作为你的内部类怎么样?

所以你的代码应该如下所示。

public class Login extends Activity {

    //declare global Views here

    protected void onCreate(Bundle bundle) {
        //Setup views
    }

    protected void onClick(View v) {
        new AsyncClass().execute(username, password);
    }

    public void checkSuccess(boolean success) {
        if (success) textView1.setText("Success");
        else textView1.setText("Failed");
    }

    class AsyncClass extends AsyncTask < String, String, JSONObject > {
        protected JSONObject doInBackground(String...params) {
            //access database
        }

        protected void onPostExecute(JSONObject json) {
            checkSuccess(true / false);
        }
    }
}

【讨论】:

  • 谢谢,这看起来是个好主意。但我需要我的AsyncTask 在外面,因为它被多个活动调用。
  • 如果他想重复使用它,他会如何重新使用它?
【解决方案2】:

试试这个

protected void onPostExecute(JSONObject json){
    //read the json result
    Login login = (Login)context; // object that you pass to task constructor
    login.checkSuccess(true);
}

您还可以在任务中添加进度对话框以指示某些作业执行

public class BaseTask<T> extends AsyncTask<Object, Void, T> {

public Context context;
public ProgressDialog dialog;

public BaseTask(Context context) {
    this.context = context;
    this.dialog = new ProgressDialog(context);
}

@Override
protected void onPreExecute() {
    this.dialog.setMessage(context.getResources().getString(R.string.loading));
    this.dialog.show();

}

@Override
protected T doInBackground(Object... objects) {
    //....
    return something;
}

@Override
protected void onPostExecute(T result) {
    if (dialog != null && dialog.isShowing())
        dialog.dismiss();
    // do something
}

}

【讨论】:

  • 哇它好用!你能解释一下这是什么魔法吗?谢谢
  • 没有魔法,只是你不需要直接创建你的活动对象。将您的活动传递给任务并使用它。如果将任务设为内部类,则可以从 onPostExecute() 更新 UI,如果将任务用作外部类,则可以使用活动实例或侦听器。
【解决方案3】:

您无法从异步任务线程编辑 UI。为了对 UI 线程进行更新,请使用 onProgressUpdate() 方法。此方法是您的 AsyncTask 类的一部分,实际上是在主 UI 线程中执行的(顺便说一句,我希望您将异步任务用作嵌套类,因为它被声明为 public,我猜您不是。您应该更改它)。如果您在异步任务中调用 publishProgress(...),操作系统本身会调用 onProgressUpdate() 方法。

一个小样本:

protected JSONObject doInBackground(String... params){
    publishProgress("test");
}

    /**
     * This method is part of the Async Task
     */
    protected void onProgressUpdate(String... progress) {
        login.checkSuccess(true);
    }   

【讨论】:

  • 感谢您的回答。 “嵌套类”与内部类相同吗?我虽然 onProgressUpdate() 用于填充进度条之类的东西?
  • onProgressUpdate() 用于更新 UI 线程。这取决于你在那里实际做什么。可以从更新进度条到更改文本视图等。是的,我所说的嵌套类是一个内部类。
【解决方案4】:

我会这样使用它,只需在你需要的地方覆盖你的 onPostExecute 或创建一个自己的接口

//create a object f your asyncclass and 
//override the onPostExecute where you need it
mInfo = new ASYNCCLASS({
   @Override
   public void onPostExecute(Object result){
      //doSomething something with your views!

  }
}).execute();

等待不是答案,因为您不知道 Asynctask 需要多长时间才能结束。 上面的代码没有经过测试,只是伪代码,但它应该能说明我的意思。

这里没有我的 IDE,所以如果有人在必要时纠正括号会很棒!

问候

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-16
    • 1970-01-01
    • 2021-01-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多