2013-06-27 57 views
1

我正在處理一個Android應用程序,它必須提出服務器請求,然後在請求完成時執行操作。下面是一些僞代碼,以幫助說明情況:確保回調的最佳方式始終是異步執行的?

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

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

這裏是makeRequest僞代碼的實現:如預期actionB之前

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發生,但在情況下,我們能夠避免網絡請求,SomeTask.execute立即被調用。這導致actionB出現之前actionA,這是不好的。有什麼辦法可以保證這不會發生?

我已經多次在javascript中遇到過這種情況。在這些情況下,我會將SomeTask.execute調用與setTimeoutsetImmediate包裝在一起以維護正確的異步語義。

爲了清楚起見,這裏的相同錯誤的例子在JavaScript:https://gist.github.com/xavi-/5882483

任何想法,我應該在的Java/Android的呢?

+0

爲什麼你不能makeRequest的調用之前採取行動答: 這是通過指定的AsyncTsak應該在一個線程池中運行固定的嗎? – 2013-06-27 19:31:33

+0

這是一種可能性,但它需要大量的重構。此外,我希望有一個通用的解決方案,所以我不反對這個問題。 – Xavi

+0

設置超時看起來像是一個非常hacky的解決方案 –

回答

1

歡迎來到世界的同步。互斥或鎖對象通常用於此目的。 Is there a Mutex in Java?

你的B任務應該在任務A完成時等待互斥信號。這將確保A任務在B之前完成的正確執行順序。

1

始終將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); 
} 
+0

這很有道理。不幸的是我簡化了我的例子。 canDoOptimization檢查和實際網絡調用發生在不同的地方。 SomeTask對象被傳遞了很多。也許我可以將'task.onDone()'調用包裝在一個虛擬的'AsyncTask'中? – Xavi

+0

一個虛擬的AsyncTask值得一試。我其實不是Android專家,我是在黑暗中拍攝的:) – jimbojw

0

爲什麼你不能只改變事物的順序?

// 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在同一個線程上運行,這意味着如果你有幾個任務,他們可以互相阻塞。

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