【问题标题】:Reset AsyncTask to multiple execution将 AsyncTask 重置为多次执行
【发布时间】:2019-01-24 14:23:18
【问题描述】:

有没有办法多次使用AsyncTask.execute()

我正在使用AsyncTask 检查我的房间数据库中是否存在User

我的 Login.class 看起来像这样:

public class Login extends AsyncTask<String, Boolean, Boolean> {

public Login(Context context, LoginListener listener){
    db = ApplicationDatabase.getDatabase(context); //i get Room here
    this.context = context; //context of app
    this.listener = listener; //my interfece for observe Boolean, works ok
}

@Override
protected Boolean doInBackground(String... body){
    try {
        user = db.userDao().getUser(body[0], body[1]);
        if (user != null)
            return Boolean.TRUE; //we find user with credentials
        else {
            return Boolean.FALSE; //we not find user with that credentials (from body)
        }
    }
    catch(Exception e){
        return null;
    }
}

protected void onPostExecute(Boolean result) {
    listener.onLoginPerformed(result); //Boolen to activity
    selfRestart(); //i want to restart task here
}

private void selfRestart(){
    //maybe something to do here? its my own method
}

private ApplicationDatabase db;
private User user;
private LoginListener listener;
private Context context;

我这样调用Task(我的Activity.class):

login = new Login(getApplicationContext(), this); 
//this is an interface that i implements in Activity definition

loginButton.setOnClickListener(new View.OnClickListener(){
        @Override
        public void onClick(View v){
            //execute() here, i cuted some not necesery code from here
            try {
                // im using get because i want to get valu from AsyncTask
                login.execute(email, password).get();
            }
            catch(Exception e){ }
}

我读到,我们可以通过创建新的AsyncTask (Task = new Login()) StackOverflow Thread 来重置AsyncTask,但这对我不起作用。当我尝试在我的Login 课堂上做这样的事情时:

private void selfRestart(){
    Login task = new Login(context, listener);
    task.execute("");
    //im calling it in onPostExecute()
}

我的安卓应用崩溃了。我的问题是,重置 AsyncTask 的最佳方法是在不同的文件中实现,然后是我的 Activity 类?或者也许有比在AsyncTask 中实现整个登录逻辑更好的方法来制作Login 活动?

编辑:

Logcat:

2019-01-24 15:45:31.407 1048-1048/com.example.admin.keystroke_dynamics E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.admin.keystroke_dynamics, PID: 1048
java.lang.NullPointerException: Attempt to invoke virtual method 'boolean java.lang.Boolean.booleanValue()' on a null object reference
    at com.example.admin.keystroke_dynamics.Activities.LoginActivity.onLoginPerformed(LoginActivity.java:62)
    at com.example.admin.keystroke_dynamics.Login.onPostExecute(Login.java:38)
    at com.example.admin.keystroke_dynamics.Login.onPostExecute(Login.java:14)
    at android.os.AsyncTask.finish(AsyncTask.java:692)
    at android.os.AsyncTask.-wrap1(AsyncTask.java)
    at android.os.AsyncTask$InternalHandler.handleMessage(AsyncTask.java:709)
    at android.os.Handler.dispatchMessage(Handler.java:105)
    at android.os.Looper.loop(Looper.java:156)
    at android.app.ActivityThread.main(ActivityThread.java:6523)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:942)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:832)

【问题讨论】:

  • "我的 android 应用程序崩溃" -- 使用 Logcat 检查与您的崩溃相关的堆栈跟踪。 “或者也许有比在 AsyncTask 中实现整个登录逻辑更好的方法来进行登录活动?” -- 让 Room 返回您的活动观察到的 LiveData,您应该不再需要 AsyncTask
  • 我更新了我的帖子,但我从logcat 获得了例外。我在 C# 堆栈中工作。当我制作我的房间数据库时,我基于谷歌的CodeLabs 示例。我认为不需要LiveData 来检查用户凭据。如果LiveData 更好,你能举个例子吗?

标签: java android android-asynctask android-room


【解决方案1】:

你说,

我这样称呼Task(我的Activity.class):

login = new Login(getApplicationContext(), this); 
//this is an interface that i implements in Activity definition

loginButton.setOnClickListener(new View.OnClickListener(){
        @Override
        public void onClick(View v){
            //execute() here, i cuted some not necesery code from here
            try {
                // im using get because i want to get valu from AsyncTask
                login.execute(email, password).get();
            }
            catch(Exception e){ }
}

,但是不,您不是以这种方式“调用”您的任务。您正在创建任务的单个实例,并设置一个事件处理程序来执行该任务 - 那个特定的实例 - 每当单击 loginButton 时。由于每个AsyncTask 实例只能执行一次,因此第二次单击登录按钮时将失败(如果不是更早,则出于其他原因)。

你也说,

我读到,我们可以通过创建新的AsyncTask (Task = new Login()) 来重置 AsyncTask

,但是 no,不会重置任何东西,而且确实无法重置 AsyncTask 对象。您阅读的建议是替换用过的AsyncTask 用一个新的实例。实例化一个新的AsyncTask 对其他人没有特别的影响。如果你想采用这种方法,那么它可能看起来像这样:

loginButton.setOnClickListener(new View.OnClickListener(){
        @Override
        public void onClick(View v){
            Login myLoginTask = login; // keep a reference to the current task
            login = new Login(... arguments ...); // create a new task for the next click

            try {
                // use the original task
                myLoginTask.execute(email, password).get();
            }
            catch(Exception e){ }
}

该特定实现要求login 不是final,因此可能是包含类的实例变量,而不是摘录代码的方法的局部变量。

但是,您最好的前进方式很可能是完全放弃AsyncTask。当你像这样使用它时:

                login.execute(email, password).get();

...你打败了整个目的。您正在使运行的线程阻塞,直到任务完成(这就是AsyncTask::get for),因此该任务实际上是同步的。如果这是您需要的,那么您应该更直接地完成所需的工作,而不是将其包装在 AsyncTask 中。

【讨论】:

  • 您的回答说明了很多,谢谢!但有一个问题。我可以在buttonClick 之外调用我的应用程序的Context,但我无法获得this,这是我的Activity 类的实现接口。我在说什么,这是this 声明:login = new Login(context, this);this 被实现时观察者进入活动以在我的AsyncTask 中捕获onPostExecute() 的变化
  • 我可以为Login AsyncTask 创建一个构造函数,它接受Login 对象并替换它吗?
  • 然后我可以使用:login = new Login(context, this) ... 点击这里按钮,然后 .... Login newTask = new Login(login);? Because i have a problem with interface taht i implements and context (i can simply call context from outside of button click, but i cant get this` 作为界面)
  • @michasaucer,您可以为Login 创建一个构造函数,从另一个Login 实例读取所需的详细信息,但构造函数本身不能用对新实例的引用替换对原始实例的引用。这是调用构造函数的代码的工作。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多