簡體   English   中英

Android后台任務,UI線程和配置更改

[英]Android background tasks, the UI Thread and configuration changes

為了解決跨配置更改保存后台任務的問題,我決定執行以下操作,而不是保留片段:

  • onSaveInstanceState(Bundle savedState)
    • 取消任何當前正在運行的任務
    • 把他們的身份證放在捆綁中
  • onRestoreInstanceState(Bundle savedState)
    • 重新啟動所有捆綁包中包含其ID的任務

由於我要處理的任務不是特別長,因此重新啟動它們不是問題,這不像我要下載大文件一樣。

這是我的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]));
        }
    }
}

因此,前提是我在UI線程中調用addTask() ,所以,僅在UI線程上執行pendingTasks.remove() pendingTasks.put()pendingTasks.remove() addTask() ,不需要任何同步。

在這一點上,我有一些問題:

  • UI線程上是否執行活動生命周期方法onSaveInstanceState()onRestoreInstanceState()
  • executor.shutdown()是否立即返回?

該文檔說executor.shutdown()等待任何先前提交的任務完成。 因此,從執行程序服務的角度來看,任務在執行完最后一條命令后就完成了,在本例中為handler.post() 因此,如果我處於onSaveInstanceState()時有任何待處理的任務,則有可能在執行程序關閉后,UI線程中將有一些已發布的可運行對象可以執行,對嗎? 而且由於我處於onSaveInstanceState()該活動可能會被破壞,而在onRestoreInstanceState()我將有一個新的活動嗎? 那么我在其中操作一些舊視圖的可運行對象會發生什么呢? 重新創建活動后,將立即執行這些可運行對象嗎? 如果在將可運行對象發布到UI線程之前,先檢查執行器當前是否正在關閉並且僅在不關閉時才執行,這會更好嗎? 在這種情況下,我可以絕對確定在調用executor.shutDown()之后executor.isShutdown()將返回true還是我必須等待任何任務完成?

  • UI線程上是否執行活動生命周期方法onSaveInstanceState()和onRestoreInstanceState()?

  • 該文檔說executor.shutdown()等待任何先前提交的任務完成。

    否。您在哪里看到該文檔? ExecutorService.shutdown讀取: This method does not wait for previously submitted tasks to complete execution. Use awaitTermination to do that This method does not wait for previously submitted tasks to complete execution. Use awaitTermination to do that

    • 那么我在其中操作一些舊視圖的可運行對象會發生什么呢?

    沒什么好的。 他們處理的活動已被破壞。 您應該舉一個標志並放棄task.onPostExecute() ,或者保存它,直到重新創建活動。 請注意,您不能將它們保存在onSaveInstanceState() -無論活動是否存在,可運行對象本身都應考慮在內。

    • 重新創建活動后,將立即執行這些可運行對象嗎?

    不,直到您照顧好它們。 重新創建活動不僅應重新啟動后台任務,還應重新啟動具有onPostExecute可運行onPostExecute

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM