2013-03-14 55 views
5

我目前正在開發具有以下需求的Android應用程序:從服務線程回撥Android活動的首選方式是什麼

工作線程在服務中啓動。此線程執行一些處理,需要從主Activity調用併爲同一個Activity提供一些異步答案。

調用從活動的服務是很容易(的IBinder東西)

我現在的問題是關於適當的服務實現回調。

我首先要在Activity中添加一個android.os.Handler,並在MyActivity.handleMessage(Message)中處理線程的聲音,但是這要求我給這個處理程序對該服務的引用。那麼當Android操作系統決定銷燬/重新創建我的活動時會發生什麼情況,例如,由於方向變化?我的活動是否保持活躍狀態​​,因爲它在服務中被間接地引用了?無論如何,如果該活動銷燬/重建,那麼服務中的Handler引用會發生什麼?

我想我沒有使用正確的方法從服務線程回調一個Activity,所以我想知道是否有人能指出我正確的做法。

TIA

+0

我知道我可以在onPause/onResume中的服務中添加/刪除Activity的Handler,但我想知道是否有更好的API我錯過了 – alberthier 2013-03-14 15:46:50

回答

4

我更喜歡使用LocalBroadcastManager

這裏是爲您的Activity代碼示例:

BroadcastReceiver localBroadcastReceiver = new BroadcastReceiver() 
{ 
    @Override 
    public void onReceive(Context context, Intent intent) 
    { 
     Log.d("BroadcastReceiver", "Message received " + intent.getAction()); 
     Log.d("BroadcaseReceiver", "Received data " + intent.getStringExtra("com.my.package.intent.EXTRA_DATA")); 
    } 
}; 

@Override 
protected void onStart() 
{ 
    super.onStart(); 
    final LocalBroadcastManager localBroadcastManager = 
     LocalBroadcastManager.getInstance(this); 
    final IntentFilter localFilter = new IntentFilter(); 
    localFilter.addAction("com.my.package.intent.ACTION_NAME_HERE"); 
    localBroadcastManager.registerReceiver(localBroadcastReceiver, localFilter); 
} 

@Override 
protected void onStop() 
{ 
    super.onStop(); 
    final LocalBroadcastManager localBroadcastManager = 
     LocalBroadcastManager.getInstance(this); 
    // Make sure to unregister!! 
    localBroadcastManager.unregisterReceiver(localBroadcastReceiver); 
} 

在你的代碼庫在別的地方(比如在你的後臺線程完成):

final LocalBroadcastManager localBroadcastManager = 
    LocalBroadcastManager.getInstance(context); 
final Intent intent = new Intent("com.my.package.intent.ACTION_NAME_HERE") 
intent.putExtra("com.my.package.intent.EXTRA_DATA", yourBackgroundData); 
localBroadcastManager.sendBroadcast(intent); 

當然,您可以使用intent.putExtra添加任何附加數據或使用多個操作來區分廣播消息。

0

一種解決方案,就像你說的,就是用MyActivity.handleMessage(消息)。每當您的活動開始(或重新開始)時,您可能會嘗試啓動該服務(您提到的「onBind」)。如果服務已經運行,則不會造成傷害。一旦綁定的東西完成,你告訴服務的信使發送回覆。

爲了確保重新啓動得到處理,在onStop中,您需要通知服務從它的「發送回覆的地方列表」中刪除該Messenger,以便它不會意外地將消息發送到現在不存在的Messenger 。當onStart作爲重新啓動的一部分被調用時,它會發送現在正確的Messenger。

顯然這需要服務處理這個並以某種方式管理它有響應的情況下發送,而沒有Messenger發送給它。它可以保存信息,直到信息可用或者信息丟失,並且Activity將顯式獲取所有狀態信息,作爲它在onStart中完成的綁定內容的後續操作。

另一種方法是讓活動每隔10秒鐘輪詢一次服務,當它知道正在進行處理以查看結果是否可用時,然後在所有信息返回後停止輪詢。

0

對於異步服務調用,我會說在啓動它時會傳遞一個回調引用。

回調函數將由binder方法執行,這是此方法的標準。

當然,啓動調用的Activity可以依賴於binder線程在其自己的進程中運行的事實。所以從回調中回到主/ UI線程是很容易的。

因此,如果回調需要在主/ UI線程來處理的東西,它只是使用

(new Handler(Looper.getMainLooper()).post() 

它有它動態地發現主/ UI線程的時間點利時代碼被執行。另一方面,這甚至不是必須的,因爲主/ UI線程沒有改變,所以通過查看引用或回調中的其他任何東西可以在回調中找到它也可以。

3

我們通過集中Application類中的活動和服務之間的所有通信來完成此操作。我們擴展Application類,然後在那裏有方法綁定到服務並接受回調。在此架構中,ActivityService之間沒有直接連接。

這種機制的優點是,您不必擔心在活動轉換和活動死亡和娛樂期間解除綁定/重新綁定到服務。 Application課程管理所有這些,並且它不受任何活動的影響。 Application類接收所有回調,並且您需要在那裏有代碼來確定如何處理回調。可能您會希望在Application類中存儲一些數據,然後通知存在新數據或類似情況的活動。

另一種方法是讓Service廣播回調。在這種情況下,服務和活動之間的耦合是鬆散的,因此您不需要在活動中創建Handler,然後將其傳遞給Service。活動只需註冊BroadcastReceiver即可獲得他們感興趣的回調,或者您可以在清單中進行管理。

+0

爲什麼不直接使用直接綁定到應用程序的'Service'?在這種情況下,只要'Application'生存就會生存,並且不需要爲'Application'類本身添加額外的邏輯。 – 2013-03-14 16:22:31

+0

@DmitryZaitsev我不確定我是否理解你的評論。我所描述的是將服務直接綁定到應用程序。然而,業務邏輯通常在活動中,他們決定何時綁定,什麼時候解除綁定,何時從服務請求某些東西等。「Application」類只是用作「代理」,管理活動之間的傳輸和服務。 – 2013-03-14 16:49:35

+0

啊,對不起,我誤解了你的答案。 – 2013-03-15 12:51:58

相關問題