为了解决跨保存配置更改后台任务的问题,我已经决定,而不是保持一个片段,做到以下几点:Android的后台任务,UI线程和配置更改
-
在
- :
- 取消任何当前正在运行的任务
- 把自己的ID在包
- 在
onRestoreInstanceState(Bundle savedState)
:- 重新启动任何任务,其ID是在包
onSaveInstanceState(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线程上执行,前提是我称之为addTask()
在UI线程,所以我不需要任何同步。
在这一点上,我有一些问题:
- 是在UI线程上执行的活动的生命周期方法
onSaveInstanceState()
和onRestoreInstanceState()
? executor.shutdown()
立即返回?
该文档说,executor.shutdown()
等待任何以前提交的任务来完成。因此,从执行程序服务的角度来看,任务在执行最后一个命令后完成,在这种情况下为handler.post()
。因此,如果我在onSaveInstanceState()
中有任何未完成的任务,那么在执行程序关闭后,UI线程可能会发布一些可执行的runnables,对吧?因为我在onSaveInstanceState()
该活动可能会被破坏,并在onRestoreInstanceState()
我会有一个新的活动?那么对于可运行的应用程序会发生什么,我在哪些操作过程中操纵了一些旧视图?活动重新创建后,这些可运行的程序会立即执行吗?如果在我发布一个可运行的UI线程之前,我检查执行程序是否正在关闭,并且只有在它不是时才执行它?在这种情况下,我可以绝对确定executor.isShutdown()
将在我调用executor.shutDown()
后返回true
,还是必须等待任何任务完成?
对不起,我应该让自己更清楚。我的意思是在'executor.shutdown()'被调用之后,任何当前正在运行的任务都将被完成,而不是过早终止。那么'executor.shutdown()'立即返回,我可以依靠'executor.isShutdown()'事后返回'true'吗? –
executor.shutdown()立即返回并且executor.isShutdown()变为true,但检查所有任务是否已完成使用isTerminated()。 –
如果当我输入'onSaveInstanceState()'时,以及在更改关闭执行程序之前,UI线程已经发布了一些可运行的函数。是否可以通过UI线程输入'onSaveInstanceState()'来发布一些等待执行的runnables,或者Android确保不会发生? –