2015-09-25 58 views
1

我有一個循環就打電話給服務:安卓:讓呼叫服務線程安全

context.startService(intent); 

在和希望後,在服務完成其處理爲每個請求返回的結果。所以我傳遞一個唯一的ID來意圖區分響應。

但不幸的是,調用onStartCommand的startService不是線程安全的。這導致響應總是最後一個id,因爲意圖在稍後的調用中被改變。

的服務代碼是相似的:

public class MyService extends Service { 
    protected Bundle rcvExtras; 

    @Override    
    public int onStartCommand(Intent intent, int flags, int startId) { 
     rcvExtras = intent.getExtras(); 
     // Todo with information in rcv Extra 
     BaseRestClient restClient = new BaseRestClient(rcvExtras.getString(Constants.INTENT_KEY_OBJECT_TYPE)); 
     restClient.post(data, rcvExtras.getString(Constants.INTENT_KEY_URL), new CallBackHandler(this)); // This is an async call 
     return super.onStartCommand(intent, flags, startId); 
    } 

    private class CallBackHandler extends Handler { 
     private final WeakReference<MyService> myServiceRef; 

     public CallBackHandler(MyService myService) { 
      myServiceRef = new WeakReference<>(myService); 
     } 

     @Override 
     public void handleMessage(Message msg) { 
      Intent result = new Intent(Constants.WS_CALL_BACK); 
      rcvExtras.putInt(Constants.INTENT_KEY_STATUS, msg.what); 
      result.putExtras(rcvExtras); 
      log.info("Broadcast data"); 
      sendBroadcast(result); // Broadcast result, actually the caller will get this broadcast message. 

      MyService myService = myServiceRef.get(); 
      log.info("Stopping service"); 
      myService.stopSelf(startId); 
     } 
    } 
} 

我怎樣才能讓服務調用線程安全的嗎?

+0

有人可以幫我嗎? –

+0

是的,這是我所有的代碼,沒有其他相關的代碼。 –

回答

2

我可以看到你的問題,這是不是框架造成的程序問題。在你調用stopself之前,你需要調用startService,你的MyService是單例,你的rcvExtras是一個全局變量,並且將在線程之間共享。

它是簡單的修復:

  • 移動rcvExtras的申報方法的範圍,這裏是onStartCommand。
  • 擴展CallBackHandler以允許您的rcvExtras,並在回調後使用它。

在這個時候你沒有任何可以共享的可擴展的,你安全。

希望得到這個幫助。

+0

啊,是的,你救了我的命,非常感謝你。一個愚蠢的代碼存根。 –