簡體   English   中英

保證回調始終是異步執行的最佳方法?

[英]Best way to guarantee a callback is always executed asynchronously?

我正在使用一個Android應用程序,該應用程序必須發出服務器請求,然后在請求完成時執行操作。 這是一些偽代碼來幫助解釋這種情況:

makeRequest(new SomeTask{
    onDone() {
        // Do actionB with queue
    }
});

// Do actionA with queue.  Must be execute first!!

這是偽代碼中的makeRequest的實現:

makeRequest(SomeTask task) {
    if(canDoOptimization) { // if true, don't need to make request

        // It's a bad idea to execute this immediately.
        // Wish I could wait until the current thread of execution was done...
        task.onDone();
        return;
    }

    asyncTask = new AsyncTask<SomeTask, Void, Void>() {
        doInBackground(SomeTask... task) {
            // Make server request...

            task.onDone();
        }
    }
    asyncTask.execute(task);
}

通常, actionA會按預期在actionB之前發生,但是在可以避免網絡請求的情況下,會立即調用SomeTask.execute 這導致actionB actionA 之前 actionA ,這是不好的。 有什么辦法可以保證不會發生這種情況嗎?

我在javascript中多次遇到這種情況。 在這些情況下,我將使用setTimeoutsetImmediate包裝SomeTask.execute調用以維護適當的異步語義。

為了清楚起見,下面是JavaScript中相同錯誤的示例: https : //gist.github.com/xavi-/5882483

知道我應該在Java / Android中做什么嗎?

歡迎來到同步世界。 互斥鎖或鎖定對象通常用於此目的。 Java中是否有Mutex?

您的B任務應等待互斥量,而互斥量將在任務A完成時發出信號。 這將確保正確的執行順序,其中A任務將在B之前完成。

始終將task.onDone()放在AsyncTask ,即使它不必發出請求也是如此。

makeRequest(SomeTask task) {

    asyncTask = new AsyncTask<SomeTask, Void, Void>() {
        void doInBackground(SomeTask... task) {

            if(canDoOptimization) { // if true, don't need to make request

                // It's a bad idea to execute this immediately.
                // Wish I could wait until the current thread of was done...
                task.onDone();
                return;
            } else {
                // Make server request...

                task.onDone();
            }
        }
    }
    asyncTask.execute(task);
}

您為什么不能只切換事物順序?

// Do actionA with queue.  Must be execute first!!

makeRequest(new SomeTask{
onDone() {
    // Do actionB with queue
});

如果actionA也是異步的並且在單獨的AsyncTask上執行,則可以在actionA的AsyncTasks的onPostExecute()方法上調用makeRequest(...)。

順便說一句,從Android Honeycomb版本開始,AsyncTasks在同一線程上運行,這意味着如果您有多個任務,它們可能會相互阻塞。 通過指定AsyncTsak應該在線程池中運行來解決此問題:

if (Build.VERSION.SDK_INT>=Build.VERSION_CODES.HONEYCOMB) {
asyncTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
}
else {
  asyncTask.execute();
}

暫無
暫無

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

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