【问题标题】:Returning boolean from onPostExecute and doInBackground从 onPostExecute 和 doInBackground 返回布尔值
【发布时间】:2019-06-18 04:28:34
【问题描述】:

我正在为我的问题寻找解决方案。

我在Activity 中调用AsyncTask

login.execute(emailText.getText().toString(), passwordText.getText().toString());

在类 Login i 中检查用户是否存在。

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

public Login(Application application){
    repository = new Repository(application);
}

@Override
protected Boolean doInBackground(String... body){
    try {
        user = repository.getUser(body[0], body[1]);
        if (user != null)
            return true; //wont work
        else {
            return false;
        }
    }
    catch(Exception e){
        return null;
    }
}

protected void onPostExecute(Long result) {
   //i want to have bool value here that i will see in my activity
}

我的问题是,如果条件匹配,如何从AsyncTask 获取bool 值?如果有任何可能的方式来调用这样的方法?

boolean valid = login.execute();

感谢您的帮助

【问题讨论】:

  • AsyncTask 你会很高兴的。同样基于此,此方法的正确签名将是 void onPostExecute(Boolean result)。

标签: java android android-asynctask


【解决方案1】:

像这样构建你的 asyncTask:

public class Login extends AsyncTask<Void, Void, Void> {

private boolean valid;

@Override
public Void doInBackground(Void... records) {
    // do work here
    user = repository.getUser(body[0], body[1]);
    if (user != null)
       valid = true;
    else
       valid = false;
    return null;
}

@Override
protected void onPostExecute(Void result) {
    callMyMethodWithTheUpdatedValue(valid);
}

}

【讨论】:

  • 您能否解释一下,callMyMethodWithTheUpdatedValue(valid)` 的作用以及如何调用它?
  • onPostExecute 是在 doInbackground 之后从主线程调用的,因此您可以使用正确的值调用 Activity 中定义的任何其他方法;而不是从 AsyncTask 返回值。看看这个了解更多细节:stackoverflow.com/a/15762539/5382017
  • 感谢您的建议,但参考两个整个对象和一个 boolean 我认为它太多了。没有简单的方法可以从 onPostExecute() 返回 bool
  • 如果你想在 onPostExecute 之后做出反应,你可以修改你的代码并实现一个接口来做到这一点:基本上你在你的活动中实例化一个监听器并从你的 onPostExecute( )。再次点击此链接以获取更多信息:stackoverflow.com/a/13815960/5382017
【解决方案2】:

更改您的代码,如下所示:

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

public Login(Application application){
    repository = new Repository(application);
}

@Override
protected Boolean doInBackground(String... body){
    try {
        user = repository.getUser(body[0], body[1]);
        if (user != null)
            return Boolean.TRUE; //wont work
        else {
            return Boolean.FALSE;
        }
    }
    catch(Exception e){
        return Boolean.FALSE;
    }
}

protected void onPostExecute(Boolean result) {
   //i want to have bool value here that i will see in my activity
   Log.e("POST_EXECUTE", "" + result);
}

【讨论】:

  • 如何在我的活动中获得result?我认为这是我唯一不明白的事情
  • onPostExecute调用活动方法并传递值
【解决方案3】:

onPostExecute() 参数类型更改为Boolean,然后告诉谁会对结果感兴趣。

对于最后一部分,您可以拥有一个接口并让某人(感兴趣的类)实现它。

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

  private LoginListener listener;

  public Login(Application application, LoginListener listener){
    repository = new Repository(application);
    this.listener = listener;
  }

  @Override
  protected Boolean doInBackground(String... body){
    try {
        user = repository.getUser(body[0], body[1]);
        if (user != null)
            return true; //wont work
        else {
            return false;
        }
    }
    catch(Exception e){
        return null;
    }
  }

  protected void onPostExecute(Boolean result) {
   listener.onLoginPerformed(result)
  }



  public static interface LoginListener{
    public void onLoginPerformed(Boolean result);
  }
}

然后假设您希望 MainActivity 在登录时做出反应:

public class MainActivity extends AppCompatActitvity implements LoginListener{
    ....
    // When you create the Login object, in onCreate() for example:
    // new Login(application, this); // this is the activity acting as listener...

    @Override public void onLoginPerformed(Boolean result){
        // do what you want to do with the result in Main Activity
    }

}

【讨论】:

    【解决方案4】:

    AsyncTask 的想法不是“获得”结果,而是在不阻塞 UI 的情况下在后台发生一些事情。您的方法将阻塞 UI 线程,直到服务器返回响应,应用程序将被阻塞,如果该状态保持超过 5 秒,用户将看到 ANR

    但要回答您的问题: 为了从 AsyncTask 获得布尔结果,您需要扩展正确的类,在您的情况下是:AsyncTask&lt;String, Void, Boolean&gt;,因为 AsyncTask 类型如下:

    异步任务使用的三种类型如下:

    Params,执行时发送给任务的参数类型。

    Progress,后台计算时发布的进度单位类型。

    Result,后台计算结果的类型。

    所以要回答你的问题,你的代码将是:

    //USAGE
    Login l = new Login();
    Boolean valid = l.execute("user", "pass").get(); 
    /* but the UI thread will be 
    blocked, meaning the following code will not be executed until the variable 
    valid is populated */ 
    
    //AsyncTask
    public class Login extends AsyncTask<String, Void, Boolean> {
    
    public Login(Application application){
        repository = new Repository(application);
    }
    
    @Override
    protected Boolean doInBackground(String... strings){
        try {
            user = repository.getUser(strings[0], strings[1]);
            if (user != null)
                return true; //wont work
            else {
                return false;
            }
        }
        catch(Exception e){
            return null;
        }
    }
    
    protected void onPostExecute(Boolean result) {
       // this method is no longer needed since you will get the result directly 
       // from the doInBackground method
    
    }
    

    也没有实际可行的解决方案: 我建议每次用户想要登录应用程序时都应该显示一个progressDialog 窗口,通知用户它必须执行一项耗时的任务,并在该过程完成后通知用户状态。 为此,请使用以下代码:

    //USAGE
       @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_test);
            Login l = new Login();
            l.execute("user", "pass"); 
            /* but the UI thread will be 
            blocked, meaning the following code will not be executed until the                             
            variable valid is populated */
        }
    
    public void userLoggedIn() {
        // do something when a user loggs in sucessfully
    }
    
    public void wrongCredentials() {
        // alert the user that he didn't put in the correct credentials
    }
    
    //AsyncTask
    public class Login extends AsyncTask<String, Void, Boolean> {
    
    
        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            // show a dialog window here when the AsyncTask starts
        }
    
        @Override
        protected Boolean doInBackground(String... strings){
            try {
                user = repository.getUser(strings[0], strings[1]);
                if (user != null)
                    return true; //wont work
                else {
                    return false;
                }
            }
            catch(Exception e){
                return null;
            }
        }
    
           @Override
        protected void onPostExecute(Boolean aBoolean) {
            super.onPostExecute(aBoolean);
            // dismiss the dialog window here after the AsyncTask finishes
            if (aBoolean) {
                userLoggedIn();
            } else {
                wrongCredentials();
            }
        }
    }
    

    【讨论】:

    • 感谢精彩重播!但我想将 Login AsyncTask 类存储在不同的 java 文件中。是否可以在 login 类中显示类似进程对话框的内容?
    • “进程对话框”?你的意思是“进度对话框”吗?
    • 是的,进度对话框
    • 即使 AsyncTask 位于单独的文件中,您也可以显示进度对话框(但由于它已被弃用,我建议使用其他替代方法 - 为了便于理解,我只是将其称为)。只需从您在 AsyncTask 的构造函数中调用 AsyncTask 的活动传递一个上下文,并将该上下文用于“进度对话框”
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-12-13
    • 1970-01-01
    • 2018-08-22
    • 1970-01-01
    • 2016-06-02
    • 2013-03-11
    • 2018-06-03
    相关资源
    最近更新 更多