2011-07-06 54 views
8

我創建了一個服務,在後臺線程上同步來自Web的數據,並希望在服務完成時通知列表活動,以便它可以更新它的遊標?什麼是最好的方法來做到這一點?我正在考慮在服務完成時發送廣播,但不確定這是否是最好的方式。當服務完成後,我需要重新查詢光標,所以我不確定這是否適用於廣播接收機?我有一段時間沒有做很多的機器人,所以提前感謝。安卓服務通知活動完成最佳方式?

回答

15

在您的服務中使用Handler,該服務在您的ListActivity連接到服務時註冊客戶端;即在您的ListActivityonServiceConnected方法中,向您的服務發送一個Message,使您可以跟蹤連接的客戶端。然後,您可以簡單地在Service中循環訪問這些客戶端,並在您想要通知ListActivity時在Service發生某事時發送Message。有關更多信息,您可以查看我的正在進行的項目中的代碼:我的ListActivity和我的Service stub

總之,在你的MainActivity,啓動並綁定到你的服務有:

Intent i = new Intent(this, NetworkService.class); 
startService(i); 
bindService(i, networkServiceConnection, Context.BIND_AUTO_CREATE); 

定義使者從像服務響應消息:

Messenger messenger = new Messenger(new IncomingHandler()); 

class IncomingHandler extends Handler { 
    @Override 
    public void handleMessage(Message msg) { 
     switch (msg.what) { 
      case NetworkService.MSG_SOMETHING: 
       // do something here 
       break; 
      default: 
       super.handleMessage(msg); 
     } 
    } 
} 

,然後寫你的服務連接代碼如:

private ServiceConnection networkServiceConnection = new ServiceConnection() { 
    public void onServiceConnected(ComponentName className, IBinder service) { 
     networkService = new Messenger(service); 
     try { 
      Message msg = Message.obtain(null, NetworkService.MSG_REGISTER_CLIENT); 
      msg.replyTo = messenger; 
      networkService.send(msg); 
      log.debug("Connected to service"); 

     } catch (RemoteException e) { 
      // Here, the service has crashed even before we were able to connect 
     } 
    } 

請注意replyTo是我們剛創建的使者。

在你NetworkService,保持連接的客戶端的軌道上:

ArrayList<Messenger> clients = new ArrayList<Messenger>(); 

,並創建您的處理程序,如:

class IncomingHandler extends Handler { 
     @Override 
     public void handleMessage(Message msg) { 
      switch (msg.what) { 
       case MSG_REGISTER_CLIENT: 
        log.debug("Adding client: " + msg.replyTo); 
        clients.add(msg.replyTo); 
        break; 
       default: 
        super.handleMessage(msg); 
        break; 
      } 
     } 
    } 

然後,當你想發送一條信息給你MainActivity,只是做類似如下的事:

for (int i = 0; i < clients.size(); i++) { 
    try { 
     clients.get(i).send(Message.obtain(null, MSG_SOMETHING)); 
    } catch (RemoteException e) { 
     // If we get here, the client is dead, and we should remove it from the list 
     log.debug("Removing client: " + clients.get(i)); 
     clients.remove(i); 
    } 
} 
+0

這聽起來很有希望,仍然有點困惑,但我認爲當我嘗試實施時,這會更有意義。在執行時間和播放接收器等方面有什麼限制嗎?我會讓你知道我編碼時會發生什麼。謝謝! – marchinram

+0

不知道有關'BroadcastReceiver's,因爲這不使用這些,而是​​使用應用程序內部的'Messenger'和'Handler's。但根據我的經驗,我沒有看到任何延遲,根據我的「服務」中的事件更新我的用戶界面。希望這對你有用! – zeitkunst

5

如果你已經使用支持庫,您可以輕鬆地將使用LocalBroadcastManager的服務中的廣播重新發送回您的活動,以監聽正在發送的廣播。

使用LocalBroadcastManager可確保只有您自己的應用程序纔會收到廣播,因此您不必擔心泄露私人數據或打開潛在的安全漏洞。

另見:how to use LocalBroadcastManager?

EDIT(09/2014):

一個更好的辦法來做到這一點是使用像Otto(我的最愛)或GreenRobot/EventBus事件總線架構,以避免耦合你的組件太緊。

0

The Busy Coder's Guide to Advanced Android Development

Event Bus是服務一個偉大的方式,讓其他部分應用程序的 知道,某些工作已完成。它提供了一個標準的 通信通道(或「總線」),事件生產者和事件 消費者可以掛鉤進去。活動製作者只需將事件 交給巴士;巴士將處理將這些事件引導至相關的消費者 。這樣可以減少生產者和消費者之間的耦合,有時甚至可以減少源代碼所需的代碼量並吸收這些事件。