从回调中返回一个值,该回调位于异步任务doInBackGround中

时间:2014-03-07 09:10:22

标签: java android android-asynctask callback

我有以下代码:

这里是指向asyncHttp的doucmentation的链接: Link

这就是调用登录任务的原因:

mAuthTask = new UserLoginTask();
mAuthTask.execute((Void) null);

这是android模板活动提供的异步任务:

    public class UserLoginTask extends AsyncTask<Void, Void, Boolean> {
    @Override
    protected Boolean doInBackground(Void... params) {
        // TODO: attempt authentication against a network service.

        Network.login(mEmail, mPassword, new AsyncHttpResponseHandler() {

            @Override
            public void onSuccess(int statusCode, Header[] headers,
                    byte[] responseBody) {

                if (statusCode == 200) {
                    // Successfully got a response
                    for (int i = 0; i < headers.length; i++) {
                        if (headers[i].getName().equalsIgnoreCase("token")) {
                            // Set the token to the received value
                            Network.SetToken(headers[i].getValue());
                    // >>>>>>>      return true;   <<<<<<<<<
                        }
                    }
                }
                // >>>>> return false  <<<<<<<<<<<<

            }

            @Override
            public void onFailure(int statusCode, Header[] headers,
                    byte[] responseBody, Throwable error) {
                // Response failed :(
                  //     >>>>>>>>>>>>>>>>>> return false <<<<<<<<<<<<<
            }           
        });

        // TODO: register the new account here.
        return true;
    }

    @Override
    protected void onPostExecute(final Boolean success) {
        mAuthTask = null;
        showProgress(false);

        if (success) {
            finish();
        } else {
            mPasswordView
                    .setError(getString(R.string.error_incorrect_password));
            mPasswordView.requestFocus();
        }
    }

如何从AsyncHttpResponseHandler中返回true或false,然后将该值返回到异步任务?这样它就可以成功执行其on post方法。

我只能想到设置变量然后阻塞它。但是那个失败主义者认为它是异步的,我宁愿远离那个。

4 个答案:

答案 0 :(得分:1)

来自开发者文档

  

AsyncTask可以正确,轻松地使用UI线程。此类允许执行后台操作并在UI线程上发布结果,而无需操纵线程和/或处理程序.AsyncTask旨在成为Thread和Handler的辅助类,并不构成通用的线程框架。理想情况下,AsyncTasks应该用于短操作(最多几秒钟。)

现在说如果你真的想在onPostExecute完成,你可以这样做

public class UserLoginTask extends AsyncTask<Void, Void, Boolean> {
    @Override
    protected Boolean doInBackground(Void... params) {
        // TODO: attempt authentication against a network service.

        final ResponseContainer responseContainer = new ResponseContainer();
        Network.login(mEmail, mPassword, new AsyncHttpResponseHandler() {

            @Override
            public void onSuccess(int statusCode, Header[] headers,
                    byte[] responseBody) {

                if (statusCode == 200) {
                    // Successfully got a response
                    for (int i = 0; i < headers.length; i++) {
                        if (headers[i].getName().equalsIgnoreCase("token")) {
                            // Set the token to the received value
                            Network.SetToken(headers[i].getValue());
                    // >>>>>>>      return true;   <<<<<<<<<
                            responseContainer.result = true;
                        }
                    }
                }
                // >>>>> return false  <<<<<<<<<<<<
                responseContainer.result = false;
            }

            @Override
            public void onFailure(int statusCode, Header[] headers,
                    byte[] responseBody, Throwable error) {
                // Response failed :(
                  //     >>>>>>>>>>>>>>>>>> return false <<<<<<<<<<<<<
                responseContainer.result = false;
            }           
        });

        // TODO: register the new account here.
        return responseContainer.result;
    }

    @Override
    protected void onPostExecute(final Boolean success) {
        mAuthTask = null;
        showProgress(false);

        if (success) {
            finish();
        } else {
            mPasswordView
                    .setError(getString(R.string.error_incorrect_password));
            mPasswordView.requestFocus();
        }
    }

    private class ResponseContainer {
        public boolean result;
    }
}

答案 1 :(得分:0)

当且仅当网络呼叫在其自己的线程上运行时,您可以尝试通过确定网络呼叫使用的线程并使用Thread.join来阻止doInBackground来执行此操作。

但是,我不认为你可以保证它,因为你没有指定执行者,并且可以在你给出的代码之外进行更改。所以,如果我有这个问题,我会转换代码并使用AsyncHandler来响应网络调用的响应,完全避免嵌套的异步操作。像这样:

public void loginUser() {
    Network.login(mEmail, mPassword, new AsyncHttpResponseHandler() {

        @Override
        public void onSuccess(int statusCode, Header[] headers,
                byte[] responseBody) {

            if (statusCode == 200) {
                // Successfully got a response
                for (int i = 0; i < headers.length; i++) {
                    if (headers[i].getName().equalsIgnoreCase("token")) {
                        // Set the token to the received value
                        Network.SetToken(headers[i].getValue());
                        new RegisterUserTask(statusCode, responseBody).execute();
                    }
                }
            }
            // respond to a failed authentication.
            mPasswordView
                .setError(getString(R.string.error_incorrect_password));
            mPasswordView.requestFocus();

        }

        @Override
        public void onFailure(int statusCode, Header[] headers,
                byte[] responseBody, Throwable error) {
            // Response failed :(
              // Show some sort of error.
        }           
    });
}

public class RegisterUserTask extends AsyncTask<Void, Void, Boolean> {
    private int statusCode;
    private byte[] body;

    public RegisterUserTask(int statusCode, byte[] body) {
        this.statusCode = statusCode;
        this.body = body;
    }

    @Override
    protected Boolean doInBackground(Void... params) {
        // TODO: register the new account here.

        return true;
    }

    @Override
    protected void onPostExecute(final Boolean success) {
        mAuthTask = null;
        showProgress(false);

        if (success) {
            finish();
        }
    }
}

答案 2 :(得分:0)

Network.login不是已经异步吗?

您可以使用处理程序系统:

private static final int SUCCESS= 0;
private static final int FAIL= 1;
//In your class
    private final Handler handler = new Handler() {

        @Override
        public void handleMessage(final Message msg) {
            runOnUiThread(new Runnable() {

                @Override
                public void run() {
                    switch (msg.what) {
                        case SUCCESS:
                            finish();
                            break;
                        case FAIL:
                            mPasswordView.setError(getString(R.string.error_incorrect_password));
                            mPasswordView.requestFocus();
                            break;
                        default:
                            break;
                    }
                }
            });
        }
    };

    public class UserLoginTask extends AsyncTask<Void, Void, Boolean> {
        @Override
        protected Boolean doInBackground(Void... params) {
            // TODO: attempt authentication against a network service.

            Network.login(mEmail, mPassword, new AsyncHttpResponseHandler() {

                @Override
                public void onSuccess(int statusCode, Header[] headers,
                        byte[] responseBody) {

                    if (statusCode == 200) {
                        // Successfully got a response
                        for (int i = 0; i < headers.length; i++) {
                            if (headers[i].getName().equalsIgnoreCase("token")) {
                                // Set the token to the received value
                                Network.SetToken(headers[i].getValue());
                                handler.sendEmptyMessage(SUCCESS);
                            }
                        }
                    }
                    // >>>>> return false  <<<<<<<<<<<<
                    handler.sendEmptyMessage(FAIL);
                }

                @Override
                public void onFailure(int statusCode, Header[] headers,
                        byte[] responseBody, Throwable error) {
                    // Response failed :(
                    handler.sendEmptyMessage(FAIL);
                      //     >>>>>>>>>>>>>>>>>> return false <<<<<<<<<<<<<
                }           
            });

            // TODO: register the new account here.
            return true;
        }

        @Override
        protected void onPostExecute(final Boolean success) {

        }
    }

但我认为你不必在Network.login中使用asyncTask .. 如果它的同步可能只是一个新的线程?

new Thread() {
                @Override
                public void run() {
                    Network.login(...) {
                       ...
                    }
                };
 }.start();

答案 3 :(得分:0)

如果我明白你的意思,你的意思是找到一种方法来处理像AsyncTaskCompleted这样的事件并在那里做你的员工。解决方案是定义一个类似WebServiceCallbackProxy的接口:

public interface WebServiceCallbackProxy {

    void CallBack(char[] jsonData, String serviceName, boolean isCommunicationSucceed, HttpRequestType reguestType, String serviceTicket);
}

然后在AsyncTask中定义一个实例:

public class AsynServiceCall extends AsyncTask<String, Integer, char[]> {

WebServiceCallbackProxy proxy;
.... 
public AsynServiceCall(WebServiceCallbackProxy webServiceProxy, ProgressDialog progressDialog) {
    this.proxy = webServiceProxy;

}

然后在PostExecute上调用你的CallBackMethod:

protected void onPostExecute(char[] response) {
        if (this.progressDialog != null) {
            progressDialog.dismiss();
        }
        if(proxy != null)
            proxy.CallBack(response, this.serviceName, this.isCommunicationSucced, this.requestType, this.serivceTicket);
    }

这样做,你有一个具有OnCompleted CallBack方法的AsyncTask。