2011-04-14 92 views
3

這是我經常使用Asyntask時遇到的一個問題。聯繫UI線程的方法是調用publishProgress()&此方法接受只有一個參數類型的數組如何讓Asynctask以不同的方式更新UI

在後臺運行,這樣做複雜的計算可能需要更新使用不同類型對象在不同的​​點UI線程。

讓我說明一個例子:

...do some processing... 
// Send UI thread the integer values of the width & height of the image 
...do some more processing... 
// Send UI thread a String with custom message. 
...do some more processing... 
// Send UI thread an instance of MyObject so it can extract & display certain values 
...do some cleanup job & finish... 

然而,onProgressUpdate()接受僅一種類型的陣列。

那麼,我做出一個包羅萬象的對象類型?我怎麼知道如何下調它,因爲這個方法可以從第1,2或3行調用,所以這是什麼時間?

當然必須有一個很好的方法來實現這一目標?

編輯:我真的很想看看,如果在Android中是可能的,將是界定publishProgress1(用戶定義args1)publishProgress2(用戶定義args2)publishProgress3的一些方法(用戶定義的args3) ...

+0

我相信,你所要求的類似的變體結構http://en.wikipedia.org/wiki/Variant_type – JAL 2011-04-15 01:52:50

+0

@JAL:感謝您分享有趣的鏈接。使用運行時類型確定的Variant_type通過運行時向下轉換提醒了我非常多的Java對象類型。我真的很希望看到,如果它可能在Android中,將會是定義* publishProgress1(用戶定義的args1)*,* publishProgress2(用戶定義的args2)*,* publishProgress3(用戶定義的args3) * ... – OceanBlue 2011-04-15 14:27:14

+0

@OceanBlue VisualBasisVARIANT是一箇舊的解決方案,但我寧願看到更安全的解決方案,可能會解決使用消息和單個處理程序來啓動三個順序線程的問題。因此,啓動返回類型A的線程返回消息(0),處理程序中的陷阱消息,啓動帶消息的線程(1)返回類型B,帶消息(2)的陷阱和啓動線程等。 – JAL 2011-04-16 00:25:35

回答

4

在你的第三個情況......

//發送UI線程的MyObject的

實例......有說你會在onPostExecute()雖然說這樣做的說法取決於你的插圖意味着什麼。

你可以很容易地按照你的建議傳遞一個包羅萬象的對象。該對象可以有各種字段(整數,字符串,對象)加上一個'動作'來描述哪些字段是有效的並且需要被處理。

你可以簡單地傳遞一個int枚舉如PROCESS_INT_WIDTH_AND_HEIGHTPROCESS_STRING_MESSAGEPROCESS_OBJECT等,有什麼能阻止你這樣做......

private static class MyAsyncTask extends AsyncTask<String, int, Void> { 
    private int width; 
    private int height; 
    private String customMessage; 
    private MyObject myObject; 

    @Override 
    protected Void doInBackground(String... params) { 

     width = 10; 
     height = 10; 
     publishProgress(PROCESS_INT_WIDTH_AND_HEIGHT); 
    } 

    protected void onProgressUpdate(int... progress) { 
     if (progress == PROCESS_INT_WIDTH_AND_HEIGHT) 
      // Process width and height 
    } 
} 

換句話說,在onProgressUpdate()方法只是簡單地迴應到'命令'並相應地處理相關的專用字段。

+0

這裏的一個危險是'publishProgress()'在onProgressUpdate()'拍攝之前可能會被調用多次。如果您修改方法以使publishProgress()採用Object,並且第一個參數是您的Integer命令ID,其他參數是其餘數據,則可以避免此問題。 – CommonsWare 2011-04-14 21:17:42

+0

@CommonsWare:有效的點 - 根據涉及的任務的複雜性,它可能會導致問題。我的偏好實際上是OP所隱含的'包羅萬象'的對象,其中要執行的動作/命令被嵌入(如你所說)。從某種意義上說,這模擬了Intents可以使用的方式 - 可以在不同情況下提供相同的數據參數,但「行動」最終決定結果。 – Squonk 2011-04-14 22:02:55

+0

謝謝,我想這可能是最好的方式去解決它,在限制之下。請參閱編輯。 – OceanBlue 2011-04-15 14:41:23

0

我不認爲有任何其他方式做到這一點。使用getType方法創建基類,然後將其用作適當投射的類型。

0

在這種情況下泛型類型能工作嗎?您可以根據需要鍵入值。例如AsyncTask原型:

new AsyncTask<String, Object, List<?>>(){ 
... 

我還記得讀取AsyncTask是最適合,只能短距離的任務。考慮複雜和長時間運行的其他線程模型。

+0

服務並不是長時間運行的任務,而只是一種在後臺運行某些東西的方式。對於長時間運行的任務,即使在服務中也應該使用線程。 – advantej 2011-04-14 21:09:11

+0

不是很長時間。幾秒鐘。但是對於一個注視着固定屏幕的用戶來說,這些看起來似乎很漫長。沿着你想要做的幾件事說...顯示一條消息,然後進行一些處理,更新整數值等等。希望我的問題有道理! – OceanBlue 2011-04-14 21:11:04

+0

@OceanBlue您仍然可以考慮將您的任務分解爲較小的部分或使用較低級別的模型。 'AsyncTask'似乎不適合所有情況。也可以考慮使用所需行爲的泛型類型。 – 2011-04-14 21:37:44

0

如果你有回國在AsyncTask處理過程的相應狀態值,您可以創建AsyncTask爲每個數據/類型,你需要內部的私有成員,然後分配一個整數每個國家和onProgressUpdate(Integer...)switch(state)基於int狀態的作業從publishProgress(state)獲得。

如果你想堅持AsyncTask(這可能不是最清晰的答案我給)

2

,另一種選擇是使用不同的類在不同的時間,和測試用的instanceof類型。

然而,這聽起來像一個相對複雜的任務,所以我建議考慮使用Handler並從一個普通Thread張貼[Runnable接口] S 2,或使用runOnUiThread

你也可能需要閱讀Painless Threading

希望這有助於

菲爾Lello

+0

爲鏈接+1。這些都是很好的鏈接,我以前閱讀過它們。我認爲AsnycTask基本上是爲了避免處理程序和線程的複雜性(和潛在的缺陷)而創建的,所以我想盡可能地堅持下去。 – OceanBlue 2011-04-15 14:36:58