AsyncTask onPostExecute没有被调用

时间:2016-03-23 07:17:14

标签: android android-asynctask

我正在尝试为Android应用实现基本登录屏幕。流程如下:
1)用户输入登录信息并点击提交
2)创建并执行扩展LoginRequest的{​​{1}} 3)AsyncTask将激活一些http调用以验证用户凭证
4)应调用doInBackground来设置onPostExecute
5)Ui线程看到登录结果并继续相应。

我一直在简化代码以解决根本问题,但到目前为止还没有任何运气。以下是仍然重现问题的简化代码。

在我的活动中:

loginResults

这是通过点击监听器上的提交按钮调用的。

在LoginHelper中:

private void tryLogin(String email, String password)
{
    this.showProgress(true);
    LoginHelper loginHelper = new LoginHelper();
    LoginResult result = loginHelper.tryLogin(email, password);
    this.showProgress(false);
}

这将执行AsyncTask并等待结果继续。

LoginRequest:

TestClass test = new TestClass();
public LoginResult tryLogin(String mobileNumber, String password, int deviceId)
{
    String loginUrl = "...";
    new LoginRequest(test).execute(loginUrl);

    while (test.result == null)
    {
        try {
            Thread.sleep(1000);
        }
        catch (Exception e)
        {
            //...
        }
    }
    return test.result;
}

我在调试器中使用public class LoginRequest extends AsyncTask<String, Void, LoginResult> TestClass test; public LoginRequest(TestClass test) { this.test = test; } @Override protected LoginResult doInBackground(String... params) { LoginResult ret = null; ret = new LoginResult(1,"test"); return ret; } @Override protected void onPostExecute(LoginResult result) { this.test.result = result; } } doInBackground内的断点运行此操作。 onPostExecute正确执行并返回doInBackground值,但LoginResult断点永远不会被命中,我的代码将在onPostExecute中的while循环中等待。

4 个答案:

答案 0 :(得分:0)

它的AsyncTask因此它同时调用LoginRequest和while(test.result)。你陷入了while循环,因为test.result还没有返回。 test.result在onPostExecute()中完成,所以如果你在该函数中移动while循环它将起作用并且onPostExecute()将被调用。解决此问题的一种方法是实现回调接口。将while循环放在覆盖的回调方法中。 请参考我的回答:how to send ArrayList(Bitmap) from asyncTask to Fragment and use it in Arrayadapter

答案 1 :(得分:0)

试一下

    public class LoginRequest extends AsyncTask<String, Void, LoginResult>
    {
    TestClass test;
        LoginResult ret = null;

    public LoginRequest(TestClass test)
    {
        this.test = test;
    }
    @Override
    protected Boolean doInBackground(String... params) {
        ret = new LoginResult(1,"test");
        return true;
    }

    @Override
    protected void onPostExecute(Boolean success) {
        if(success)
            this.test.result = result;
    }
   }

答案 2 :(得分:0)

临时解决方案:您可以在this.test.result = result;方法中添加doInbackground()

@Override
 protected LoginResult doInBackground(String... params) {

            LoginResult ret = null;
            ret = new LoginResult(1, "test");
            this.test.result = result;
            return ret;
 }

请发布完整代码以获得正确的解决方案。

答案 3 :(得分:0)

您基本上是在检查LoginRequest的变量“result”的整个时间。但事实并非如此,AsyncTask如何运作。

来自Docs

  

AsyncTask允许您对用户执行异步工作   接口。它在工作线程中执行阻塞操作   然后在UI线程上发布结果,无需您   自己处理线程和/或处理程序。

您可以使用 doInBackground()方法进行工作,然后将结果发布到 onPostExecute()

onPostExecute在UI线程上运行,允许您更改元素,显示结果或您想要执行的任何操作。您的问题是,您一直在使用tryLogin()

中的检查方法阻止UI线程

那么如何解决呢?

删除检查方法:

public void tryLogin(String mobileNumber, String password, int deviceId)
{
    // Starts AsynTasks, handle results there
    String loginUrl = "...";
    new LoginRequest().execute(loginUrl);
}

在AsyncTask中:

public class LoginRequest extends AsyncTask<String, Void, LoginResult>

    // Removed Constructor, if you need to pass some other variables, add it again

    @Override
    protected LoginResult doInBackground(String... params) {

        // TODO: Change this to actual Http Request
        LoginResult ret = null;
        ret = new LoginResult(1, "test");
        return ret;
    }

    @Override
    protected void onPostExecute(LoginResult result) {
         // Now the result arrived!
         // TODO: Use the result
    }
}

更多想法:

  1. 您可能希望存储用户凭据。如果是这样,请确保安全。 Link
  2. 您可能希望根据结果更改某些UI。这是一个例子:
  3. 的AsyncTask:

    公共类LoginRequest扩展了AsyncTask

        private Activity activity;
    
        // Constructor
        public LoginRequest(Activity activity) {
           this.activity = activity;
        }
    
        @Override
        protected LoginResult doInBackground(String... params) {
    
            // TODO: Change this to actual Http Request
            LoginResult ret = null;
            ret = new LoginResult(1, "test");
            return ret;
        }
    
        @Override
        protected void onPostExecute(LoginResult result) {
    
             ActivityLogin acLogin = (ActivityLogin) activity;
    
             if(result.equals("ok")) {
                Button loginButton = (Button) acLogin.findViewById(R.id.login-button);
                loginButton.setBackgroundColor(Color.GREEN);
    
                //Finish LoginActivity
                acLogin.finish();
             }
             else {
                //TODO: Fail Handling
             }
        }
    }
    

    开始就像这样:

    new LoginRequest(loginActivity).execute(loginUrl);
    

    我没有测试过代码。