是否可以同步Android AsyncTask doInBackground以序列化任务执行?

Lor*_*ori 8 android synchronization android-asynctask

是否可以进行AsyncTask.doInBackground同步 - 或以另一种方式实现相同的结果?

class SynchronizedTask extends AsyncTask {

    @Override
    protected synchronized Integer doInBackground(Object... params) {
        // do something that needs to be completed 
        // before another doInBackground can be called
    }
}
Run Code Online (Sandbox Code Playgroud)

在我的情况下,任何AsyncTask.execute()可以在前一个完成之前启动,但我只需要doInBackground在上一个任务完成后执行代码.

编辑:正确指出,同步仅适用于同一对象实例.遗憾的是,无法在同一对象实例上创建AsyncTask和调用execute()多次,如AsyncTask 文档的"线程规则"部分所述.

解决方案是使用自定义Executor来序列化任务,或者,如果您使用API​​ 11或更高版本,AsyncTask.executeOnExecutor()则按照以下注释中的建议使用.

我发布了一个答案,显示了一个SerialExecutor可用于对将按顺序执行的任务进行排队的实现.

Lor*_*ori 16

理想情况下,我希望能够使用AsyncTask.executeOnExecutor()a SERIAL_EXECUTOR,但这仅适用于API级别11或更高级别:

new AsyncTask().executeOnExecutor(AsyncTask.SERIAL_EXECUTOR, params);
Run Code Online (Sandbox Code Playgroud)

为了定位11级以下的Android API,我最终实现了一个自定义类,它封装了ExecutorService一个线程池大小为1.完整代码在这里是开源的.

Executors.newFixedThreadPool(int nThreads)创建一个线程池,该线程池重用在共享的无界队列中运行的固定数量的线程.在任何时候,最多nThreads线程都将是活动处理任务.在我的情况下,nThreads是1,这意味着任务可以排队,但在任何给定时间只执行一个任务.

这是代码:

public abstract class SerialExecutor {
    private final ExecutorService mExecutorService;

    public SerialExecutor() {
        mExecutorService = Executors.newFixedThreadPool(1);
    }

    public void queue(Context context, TaskParams params) {
        mExecutorService.submit(new SerialTask(context, params));
    }

    public void stop() {
        mExecutorService.shutdown();
    }

    public abstract void execute(TaskParams params);

    public static abstract class TaskParams { }

    private class SerialTask implements Runnable {
        private final Context mContext;
        private final TaskParams mParams;

        public SerialTask(Context context, TaskParams params) {
            mContext = context;
            mParams = params;
        }

        public void run() {
            execute(mParams);
            Activity a = (Activity) mContext;
            a.runOnUiThread(new OnPostExecute());
        }
    }

    /**
     * Used to notify the UI thread
     */
    private class OnPostExecute implements Runnable {

        public void run() {

        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这可以扩展并用作以下的串行任务执行器Activity:

public class MyActivity extends Activity {
    private MySerialExecutor mSerialExecutor;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        // ...
        mSerialExecutor = new MySerialExecutor();
    }

    @Override
    protected void onDestroy() {
        if (mSerialExecutor != null) {
            mSerialExecutor.stop();
        }
        super.onDestroy();
    }

    public void onTrigger(int param) {
        mSerialExecutor.queue(this, new MySerialExecutor.MyParams(param));
    }

    private static class MySerialExecutor extends SerialExecutor {

        public MySerialExecutor() {
            super();
        }

        @Override
        public void execute(TaskParams params) {
            MyParams myParams = (MyParams) params;
            // do something...
        }

        public static class MyParams extends TaskParams {
            // ... params definition

            public MyParams(int param) {
                // ... params init
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


shi*_*ird 5

您可能需要考虑使用IntentService代替。看起来它可能更适合您的流程,因为它内置了排队功能。