为了解决跨配置更改保存后台任务的问题,我决定不执行以下操作而不是保留片段:
onSaveInstanceState(Bundle savedState)
中:
onRestoreInstanceState(Bundle savedState)
中:
由于我正在处理的任务不是特别长,重新启动它们不是问题,它不像我正在下载大文件或其他东西。
这是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()
?executor.shutdown()
会立即返回吗?文档说executor.shutdown()
等待以前提交的任何任务完成。因此,从执行程序服务的角度来看,任务在执行完最后一个命令后完成,在本例中为handler.post()
。所以,如果我在onSaveInstanceState()
时有任何挂起的任务,那么在执行程序关闭之后,UI线程可能会有一些已发布的runnables来执行,对吧?因为我在onSaveInstanceState()
,活动可能会被破坏,在onRestoreInstanceState()
我会有一个新的活动?那么runnables会发生什么呢?我操纵一些旧观点?重新创建活动后,是否会立即执行这些runnable?如果在我将一个runnable发布到UI线程之前,我检查执行程序当前是否正在关闭并且仅在它不是时执行它,那不是更好吗?在这种情况下,我可以绝对确定executor.isShutdown()
在我致电true
后会返回executor.shutDown()
还是我必须等待任何任务完成?
答案 0 :(得分:2)
是否在UI线程上执行了活动生命周期方法onSaveInstanceState()和onRestoreInstanceState()?
是
文档说,executor.shutdown()等待任何以前提交的任务完成。
没有。你在哪里看到那些文件? ExecutorService.shutdown读取:This method does not wait for previously submitted tasks to complete execution. Use awaitTermination to do that
。
没什么好的。他们所处理的活动已被破坏。您应该举起一个标志并放弃task.onPostExecute()
,或者保存它直到重新创建活动。请注意,您无法将它们保存在onSaveInstanceState()
中 - 无论活动是否存在,runnables本身都应该考虑在内。
不,直到你照顾他们。重新创建活动不仅应该重新启动后台任务,还应该使用onPostExecute
重新启动运行。