重复执行AsyncTask

6

我对在Android应用中重复执行AsyncTask的可能性存有疑问。例如,如果由于某些原因无法下载文件,则希望重复执行某些操作,如从服务器下载文件,执行n遍。是否有一种快速的方法可以实现这一点?


1
问题到底是什么?如果失败了,您可以再次启动相同的AsyncTask。 - Stefan de Bruijn
使用Service和AlarmManager类来重复执行异步任务。 - Mohit
3个回答

11

您不能重复执行AsyncTask,但是您可以重复执行它执行的操作。

我制作了这个小帮助类,您可能想要扩展它取代AsyncTask,唯一的大区别是您将使用repeatInBackground而不是doInBackground,而onPostExecute将有一个新参数,即最终抛出的异常。

在repeatInBackground内部的任何内容都将自动重复,直到结果不同于null /未抛出异常且尝试次数小于maxTries。

循环内抛出的最后一个异常将在onPostExecute(Result,Exception)中返回。

您可以使用RepeatableAsyncTask(int retries)构造函数设置最大尝试次数。

public abstract class RepeatableAsyncTask<A, B, C> extends AsyncTask<A, B, C> {
    private static final String TAG = "RepeatableAsyncTask";
    public static final int DEFAULT_MAX_RETRY = 5;

    private int mMaxRetries = DEFAULT_MAX_RETRY;
    private Exception mException = null;

    /**
     * Default constructor
     */
    public RepeatableAsyncTask() {
        super();
    }

    /**
     * Constructs an AsyncTask that will repeate itself for max Retries
     * @param retries Max Retries.
     */
    public RepeatableAsyncTask(int retries) {
        super();
        mMaxRetries = retries;
    }

    /**
     * Will be repeated for max retries while the result is null or an exception is thrown.
     * @param inputs Same as AsyncTask's
     * @return Same as AsyncTask's
     */
    protected abstract C repeatInBackground(A...inputs);

    @Override
    protected final C doInBackground(A...inputs) {
        int tries = 0;
        C result = null;

        /* This is the main loop, repeatInBackground will be repeated until result will not be null */
        while(tries++ < mMaxRetries && result == null) {
            try {
                result = repeatInBackground(inputs);
            } catch (Exception exception) {
                /* You might want to log the exception everytime, do it here. */
                mException = exception;
            }
        }
        return result;
    }

    /**
     * Like onPostExecute but will return an eventual Exception
     * @param c Result same as AsyncTask
     * @param exception Exception thrown in the loop, even if the result is not null.
     */
    protected abstract void onPostExecute(C c, Exception exception);

    @Override
    protected final void onPostExecute(C c) {
        super.onPostExecute(c);
        onPostExecute(c, mException);
    }
}

这个类可以作为静态类使用吗?我喜欢使用静态AsyncTasks来避免在方向改变期间出现悬空引用。你知道你的类是否可以静态工作吗? - SMBiggs
我总是静态地使用它。 - Luca Vitucci
可以在尝试之间添加类似延迟的东西吗?例如每秒进行一次查询。 - JCMiguel

1
你不能重复使用相同的AsyncTask对象,因为根据AsyncTask文档,任务只能执行一次(如果尝试进行第二次执行,则会抛出异常)。
但是,你可以在循环内部创建任意数量的该类新对象。然而,更好的方法是在doInBackground()中执行下载操作n次。
如果这不能回答你的问题,请更具体地描述你的问题。

0

我是用这种方法做的。它可以尝试多次,直到(tries == MAX_RETRY)或者结果不为空为止。这是一个稍作修改的代码,对我来说更好。

private class RssReaderTask extends AsyncTask<String, Void, ArrayList<RssItem>> {

    // max number of tries when something is wrong
    private static final int MAX_RETRY = 3;

    @Override
    protected ArrayList<RssItem> doInBackground(String... params) {

        ArrayList<RssItem> result = null;
        int tries = 0;

        while(tries++ < MAX_RETRY && result == null) {
            try {
                Log.i("RssReaderTask", "********** doInBackground: Processing... Trial: " + tries);
                URL url = new URL(params[0]);
                RssFeed feed = RssReader.read(url);
                result = feed.getRssItems();
            } catch (Exception ex) {
                Log.i("RssReaderTask", "********** doInBackground: Feed error!");
            }
        }

        return result;
    }

    @Override
    protected void onPostExecute(ArrayList<RssItem> result) {
        // deal with result
    }

}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接