简体   繁体   English

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

[英]Return a value from callback which is situated in an async task doInBackGround

I have the following bit of code: 我有以下代码:

here is a link to the doucmentation fo rthe asyncHttp: Link 这是asyncHttp的文档链接链接

This is what calls the login task: 这就是所谓的登录任务:

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

Here is the async Task provided by android template activity: 这是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();
        }
    }

How can I return true or false from within my AsyncHttpResponseHandler and then return that value to the async task? 如何从AsyncHttpResponseHandler中返回true或false,然后将该值返回给async任务? So that it can then successfully execute its on post method. 这样它就可以成功执行on post方法。

I can only think of settings variable and then blocking on it. 我只能想到设置变量,然后对其进行阻止。 But then that defeatists the point of it being async and I would rather stay away from that. 但是那次失败者认为它是异步的,我宁愿远离它。

From the developer documents 来自开发人员的文件

AsyncTask enables proper and easy use of the UI thread. 通过AsyncTask,可以正确,轻松地使用UI线程。 This class allows to perform background operations and publish results on the UI thread without having to manipulate threads and/or handlers.AsyncTask is designed to be a helper class around Thread and Handler and does not constitute a generic threading framework. 此类允许执行后台操作并在UI线程上发布结果,而无需操纵线程和/或处理程序。AsyncTask被设计为围绕Thread和Handler的帮助器类,并且不构成通用的线程框架。 AsyncTasks should ideally be used for short operations (a few seconds at the most.) 理想情况下,AsyncTasks应该用于简短的操作(最多几秒钟)。

Now that said if you really want to finish in onPostExecute you can do this 这就是说,如果您真的想在onPostExecute完成操作, 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;
    }
}

If, and only if, the Network call runs on it's own thread, you could try to do this by blocking doInBackground by figuring out which thread the network call uses and using Thread.join . 当且仅当Network调用在其自己的线程上运行时,您可以通过找出网络调用使用的线程并使用Thread.join来阻止doInBackground以尝试执行此操作。

However, I don't think you can guarantee it will, since you have not specified the executor and that can change outside the code you've given. 但是,我认为您不能保证这样做,因为您没有指定执行程序,并且可以在给定的代码之外进行更改。 So, if I had this issue, I would turn the code around and use an AsyncHandler to respond to the response of the Network call, avoiding nested async operations altogether. 因此,如果遇到此问题,我将转过代码并使用AsyncHandler来响应网络调用的响应,从而完全避免嵌套的异步操作。 Something like this: 像这样:

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();
        }
    }
}

Isn't the Network.login already async? Network.login是否已经异步?

You can use Handler system : 您可以使用Handler系统:

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) {

        }
    }

But I think you don't have to use the asyncTask with Network.login.. If it's synchrone maybe just a new Thread ? 但是我认为您不必将asyncTask与Network.login一起使用。如果同步,也许只是一个新的Thread?

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

If I get your point you mean finding a way to handle an event like AsyncTaskCompleted and do your staff there. 如果我明白您的意思,您的意思是找到一种方法来处理AsyncTaskCompleted之类的事件并在那儿工作。 The solution is defining an interface like WebServiceCallbackProxy: 解决方案是定义一个类似于WebServiceCallbackProxy的接口:

public interface WebServiceCallbackProxy {

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

Then define an instance in your AsyncTask: 然后在您的AsyncTask中定义一个实例:

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

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

}

Then call your CallBackMethod on PostExecute: 然后在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);
    }

Doing so, you have an AsyncTask that has OnCompleted CallBack Method. 这样做,您有一个具有OnCompleted CallBack方法的AsyncTask。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 从doInBackground将泛型用于不同的返回类型的异步任务 - Async task using generics for different return types from doInBackground Android:异步任务:doInBackground在操作回调之前返回 - Android: Async Task : doInBackground returns before an action callback 异步任务需要来自doInBackground的非数组返回对象,但会找到对象数组 - Async Task requires non-array return object from doInBackground but finds array of object 将字符串从异步任务的doInBackground传递到主线程 - Passing string from doInBackground of Async task to main thread 将参数从Activity传递到doInBackground方法,Async Task - Passing parameters from Activity to doInBackground method, Async Task doinbackground()在异步任务中无法正常工作 - doinbackground() in async task not working properly 在doInBackground方法中发生的异步任务#1 - Async task #1 occurring in the doInBackground method Android MultipartUploadRequest在异步任务doInBackground中不起作用 - Android MultipartUploadRequest not working in async task doInBackground 致命异常,异步任务的doInBackground()方法中的Runtimeerror - FATAL EXCEPTION, Runtimeerror in doInBackground() method of async task 异步任务执行doInBackground()时发生错误? - Async Task An error occured while executing doInBackground()?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM