【问题标题】:Android background tasks, the UI Thread and configuration changesAndroid 后台任务、UI 线程和配置更改
【发布时间】: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


    【解决方案1】:
    • 活动生命周期方法 onSaveInstanceState() 和 onRestoreInstanceState() 是否在 UI 线程上执行?

      是的

    • 文档说 executor.shutdown() 等待任何以前提交的任务完成。

      没有。你在哪里看到的那个文件? ExecutorService.shutdown 读作:This method does not wait for previously submitted tasks to complete execution. Use awaitTermination to do that

      • 那么,我在其中操作一些旧视图的可运行文件会发生什么情况?

      没什么好说的。他们处理的活动已经被破坏了。您应该提出一个标志并放弃task.onPostExecute(),或者保存它直到重新创建活动。请注意,您不能将它们保存在 onSaveInstanceState() 中 - 可运行对象本身应考虑活动是否处于活动状态。

      • 是否会在重新创建活动后立即执行这些可运行文件?

      不,直到你照顾好他们。重新创建活动不仅应该重新启动后台任务,还应该重新启动带有onPostExecute 的可运行对象。

    【讨论】:

    • 对不起,我应该让自己更清楚。我的意思是,在调用executor.shutdown() 之后,任何当前正在运行的任务都将完成,而不是提前终止。那么executor.shutdown() 是否会立即返回,我可以依靠executor.isShutdown() 之后返回true 吗?
    • executor.shutdown() 立即返回并且 executor.isShutdown() 变为 true,但要检查所有任务是否已完成使用 isTerminated()。
    • 如果当我输入onSaveInstanceState() 并且在我更改关闭执行程序之前,UI 线程已经发布了一些可运行文件,该怎么办。是否可以输入onSaveInstanceState(),UI 线程已经发布了一些等待执行的可运行文件,或者 Android 确保不会发生这种情况?
    猜你喜欢
    • 2012-06-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-07
    • 2015-07-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多