带有通知的Android AsyncTask

时间:2013-07-01 13:59:25

标签: android android-asynctask

我目前正在开发Android应用程序,我必须说这一切都非常简单明了。

我对AsyncTask有一个小问题。也许我一直在做错事,但情况就是这样。

我有一个小应用程序,需要从Web加载列表的内容。 我根据假请求开发了所有内容,这一切都很棒。然后我用实际请求更新了代码,得到了'网络主线程错误'。所以我决定切换到AsyncTask。

我想知道我是否可以让AsyncTask执行异步工作,并在其他地方处理结果(我实际上有GUI连接和所有内容)。我认为就可读性和逻辑而言,拥有处理Activity中接口的所有代码更有意义,但是我怎么能让Activity知道任务何时完成?

我写了这些简单的类和接口(并且它可以工作)但是我想知道你是否这是一件好事还是有更好的方法来做到这一点。

所以,这是代码:

public interface AsyncDelegate {

    public void executionFinished(LazyLoaderWithDelegate lazyLoaderWithDelegate);
}

这是一个简单的界面。目的是让Activity实现它并处理'executionFinished'方法。像听众一样。

import android.os.AsyncTask;

public class LazyLoaderWithDelegate<Params, Progress, Result> extends AsyncTask<Params, Progress, Result>{
    AsyncDelegate delegate;

    Result result;

    public LazyLoaderWithDelegate(AsyncDelegate delegate){
        this.delegate = delegate;
    }

    @Override
    protected Result doInBackground(Object... params) {
        //This will be Overridden again from the subclasses anyway.
        return null;
    }

    @Override
    protected void onPostExecute(Result r){
        this.result = r;
        delegate.executionFinished(this);
    }

    public Result getResult(){
        return result;
    }

}

这个类基本上给出了一个骨架结构,用于在任务完成时通知代理。

这就是全部。以下是使用此类的示例:

public class LazyVideoLoader extends LazyLoaderWithDelegate<Void, Void, List<List<Video>>>{

    public LazyVideoLoader(AsyncDelegate delegate) {
        super(delegate);
    }

    @Override
    protected List<Video> doInBackground(Void ...params) {
        return ServerInterface.getVideos();
    }

}

public class MainActivity extends Activity implements AsyncDelegate {
    private LazyVideoLoader videoLoader;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        /*
         * Set up the lazy loaders
         */
        videoLoader = new LazyVideoLoader(this);
        videoLoader.execute();
    }

    @Override
    public void executionFinished(LazyLoaderWithDelegate task) {
        if(task == videoLoader){
            List<Video> result = videoLoader.getResult();
            //Do whatever you need...
        }

}

2 个答案:

答案 0 :(得分:3)

您在onPostExecute上运行的所有内容都在UI线程中。此外,只需在onProgressUpdate上通过调用publishProgress上的doInBackground完成工作的某个部分,就可以在UI线程上运行代码。

有关详细信息,请参阅this。它包含您需要了解的有关AsyncTask的所有信息。

答案 1 :(得分:1)

如果我理解这是正确的,你有一个单独的类,它运行AsyncTask。如果任务完成,则回调使用的接口通知活动。如果您在组件中考虑使代码更加模块化,这是很好的。

最常见的做法是使用AsyncTask作为Activity中的内部类。如果你只是想下载相对较小尺寸的图片或类似的东西,这是首选方式。因为您可以访问内部类中的所有字段,这比在构造函数/接口中传递它们更容易。

为了便于阅读,请不要在额外的类中使用AsyncTask。如果你必须用不同的方法对结果做一些公平的计算/修改,你的方式就可以了。