将AsyncTask的结果传递给调用者类的最佳方法

时间:2016-05-17 16:41:11

标签: java android android-asynctask

我已经实现了一种将onPostExecute的结果返回到我的主要活动的方法。我想知道这是否是我做的正确的事情,是否有更多机会改进它,如果它不是最好的方式,最好的方法是什么?

这就是我所做的:

public class MainClass implements AsyncResponse {
    private MyAsyncTask asyncTask;

    public MainClass() {
        asyncTask = new MyAsyncTask();
        asyncTask.asyncResponse = this;
    }

    public void startTask( {
        asyncTask.execute("string");
    }

    @Override
    public void processDone(String res) {
        // got response in MainClass from onPostExecute
    }

    private class MyAsyncTask extends AsyncTask<String, String, String> {

        protected AsyncResponse asyncResponse = null;

        @Override
        protected String doInBackground(String... urls) {
            return "some processed string";
        }

        @Override
        protected void onPostExecute(String res) {
            this.asyncResponse.processDone(res);
        }
    }
}

这是AsyncResponse界面:

public interface AsyncResponse {
    void processDone(String res);
}

我想知道在平均Android移动设备上的处理速度,这是一个好方法,如果没有,我如何改进它,使其成为一个好方法?

感谢。

4 个答案:

答案 0 :(得分:0)

我总是这样做,从来没有任何问题。我会说这是最好的方式。

答案 1 :(得分:0)

在一行中没有任何回调

   String s= new MyAsyncTask().execute().get();

答案 2 :(得分:0)

您添加了一个不必要的界面 - 也许这会使您的代码不太可用。

首先,如果您在AsyncTask中创建Activity作为类,则不需要该接口。你可以这样做:

@Override
protected void onPostExecute(String res) {
    processDone(res);
}

AsyncTask将在UI线程上执行onPostExecute,您可以在没有接口的情况下调用Activity方法。

其次,如果你在AsyncTask类之外创建Activity(例如,在它自己的java文件中),那么你可以使用这个方法,除了它不是一个好主意,因为它将持有在另一个线程上引用Activity - 这是内存泄漏风险。

为了避免这种情况,您的界面应该在一个单独的类中实现,例如传递给AsyncTaskResponse.java类的AsyncTask

最后,AsyncTaskString的形式提供响应,如果这足够的话。您应该查看AsyncTask上的文档:

https://developer.android.com/reference/android/os/AsyncTask.html

答案 3 :(得分:0)

您将AsyncTask包装在另一个POJO类中;这样做并不会造成伤害,但收效甚微。

考虑到任务完成后,您将需要某处的回调通知。您的MainClass将在processDone()中收到回调,但有些内容需要收听MainClass才能收到该通知。

这是我一直用于AsyncTask子类的模式:

public class GetDataRemoteTask extends AsyncTask<String, Void, Data> {

    private static final String TAG = "GetDataRemoteTask ";

    private WeakReference<GetDataResultListener> mListenerRef;

    private Exception mExc;

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

        Data result = null;

        try {
            result = mService.getData(params[0], params[1], params[2]);

        } catch (Exception e) {
            Log.e(TAG, "Error occurred getting data", e);
            mExc = e;
        }
        return result;
    }

    @Override
    protected void onPostExecute(Data result) {

        if (mListenerRef != null) {
            GetDataResultListener listener = mListenerRef.get();
            if (listener != null) {
                if (mExc == null) { 
                    listener.dataReceived(result);
                } else {
                    listener.dataException(mExc);
                }
            }
        }
    }

    public void setGetDataResultListener(GetDataResultListener listener) {

        if (listener == null) {
            this.mListenerRef = null;
        } else {
            this.mListenerRef = new WeakReference<GetDataResultListener >(listener);
        }
    }

    public static interface GetDataResultListener {

        public void dataReceived(Data data);

        public void dataException(Exception exc);
    }

}

首先,在这里,我有一个界面,就像你一样,用于连接AsyncTask。但是我没有用我的AsyncTask包含一个实现,我希望我会有ActivityFragment来实现这个接口。 (这就是我使用WeakReference的原因;如果Activity完成,我的AsyncTask不会继续保持Activity。但这也是意味着我不能使用匿名类监听器,除非客户端持有它的引用。)

我的客户端代码如下所示:

        GetDataRemoteTask task = new GetDataRemoteTask();
        task.setListener(this);
        task.execute(param1, param2, param3);

我还可以找出后台任务中是否发生异常。应始终向客户端报告任何后台异常,这可以决定如何最好地处理异常 - 例如弹出用户对话框,以便他们知道请求失败。

我认为AsyncTask的一大缺点是它没有更多的结构来处理后台线程中发生的异常。

我的任务包含对异常的引用,但我还使用Pair<Data, Exception>作为返回结果的类型参数,因此我不需要异常属性。

使用此模式帮助我避免了编码AsyncTask子类时出现的一些典型问题。