【发布时间】:2014-05-28 02:15:27
【问题描述】:
为了解决跨配置更改保存后台任务的问题,我决定不保留片段,而是执行以下操作:
- 在
onSaveInstanceState(Bundle savedState):- 取消所有当前正在运行的任务
- 将他们的 ID 放入捆绑包中
- 在
onRestoreInstanceState(Bundle savedState):- 重新启动任何 id 在 bundle 中的任务
由于我正在处理的任务不是特别长,因此重新启动它们不是问题,也不是我要下载大文件之类的。
这是我的TaskManager 的样子:
public class BackgroundTaskManager {
// Executor Service to run the tasks on
private final ExecutorService executor;
// list of current tasks
private final Map<String, BackgroundTask> pendingTasks;
// handler to execute stuff on the UI thread
private final Handler handler;
public BackgroundTaskManager(final ExecutorService executor) {
this.executor = executor;
this.pendingTasks = new HashMap<String, BackgroundTask>();
this.handler = new Handler(Looper.getMainLooper());
}
private void executeTask(final BackgroundTask task) {
// execute the background job in the background
executor.submit(new Runnable() {
@Override
public void run() {
task.doInBackground();
handler.post(new Runnable() {
@Override
public void run() {
// manipulate some views
task.onPostExecute();
// remove the task from the list of current tasks
pendingTasks.remove(task.getId());
// check if the list of current tasks is empty
}
});
}
});
}
/**
* Adds a task to the manager and executes it in the background
*
* @param task
* the task to be added
*/
public void addTask(final BackgroundTask task) {
pendingTasks.put(task.getId(), task);
executeTask(task);
}
public void onSaveInstanceState(Bundle savedInstanceState) {
// check if there are pendingTasks
if (!pendingTasks.isEmpty()) {
executor.shutdown();
savedInstanceState.putStringArray("pending tasks", pendingTasks.keySet().toArray(new String [1]));
}
}
}
所以,pendingTasks.put() 和 pendingTasks.remove() 只在 UI 线程上执行,前提是我在 UI 线程中调用 addTask(),所以我不需要任何同步。
此时,我有一些问题:
- 活动生命周期方法
onSaveInstanceState()和onRestoreInstanceState()是否在UI 线程上执行? -
executor.shutdown()会立即返回吗?
文档说executor.shutdown() 等待任何以前提交的任务完成。因此,从执行器服务的角度来看,任务在其最后一个命令执行后完成,在本例中为handler.post()。所以,如果我在onSaveInstanceState() 时有任何待处理的任务,有可能在执行器关闭后,UI 线程将有一些已发布的可运行对象来执行,对吧?既然我在onSaveInstanceState(),活动可能会被破坏,在onRestoreInstanceState()我会有一个新活动?那么,我在其中操作一些旧视图的可运行文件会发生什么情况?重新创建活动后,这些可运行文件会立即执行吗?如果在我向 UI 线程发布一个可运行文件之前,我检查执行程序当前是否正在关闭并且仅在它没有关闭时才执行它,这不是更好吗?在这种情况下,我可以绝对确定在我调用executor.shutDown() 之后executor.isShutdown() 将返回true,还是我必须等待任何任务完成?
【问题讨论】:
标签: java android multithreading executorservice