Android:让呼叫服务线程安全

时间:2015-09-25 12:50:43

标签: android multithreading android-intent

我有一个调用服务的循环:

context.startService(intent);

In并希望在服务完成每个请求的处理后返回结果。因此,我传递了一个唯一的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);
        }
    }
}

如何让服务调用线程安全?

1 个答案:

答案 0 :(得分:2)

我可以看到你的问题,这是不是由框架引起的编程问题。在这里你可以调用startService直到你调用stopself,你的MyService是单例,你的rcvExtras是一个全局变量,将在线程之间共享。

修复很简单:

  • 将rcvExtras的声明移到方法范围,这里是onStartCommand。
  • 扩展CallBackHandler以允许你的rcvExtras,并在回调时使用它。

此时你没有任何可变量可以共享,而且你很安全。

希望得到这个帮助。

相关问题