简体   繁体   中英

synchronized block inside onReceive() callback

I am reading this page about how to program Android to talk to a USB accessory. One of the steps involves registering a BroadcastReceiver to obtain permission from the user:

IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
registerReceiver(mUsbReceiver, filter);

where mUsbReceiver is defined as:

private final BroadcastReceiver mUsbReceiver = new BroadcastReceiver() {

    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        if (ACTION_USB_PERMISSION.equals(action)) {
            synchronized (this) {
                UsbAccessory accessory = (UsbAccessory) intent.getParcelableExtra(UsbManager.EXTRA_ACCESSORY);

                if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
                    if(accessory != null){
                        //call method to set up accessory communication
                    }
                }
                else {
                    Log.d(TAG, "permission denied for accessory " + accessory);
                }
            }
        }
    }
};

What puzzles me is why synchronized (this) is used? onReceive() will be called on the UI thread and that's it. This block of code does not seem to touch any data which may be accessed by other threads, unless the object accessory counts (and there's nothing on the page that suggests it is).

I searched on the web, and there does not seem to be much emphasis on thread-safety in onReceive() (it's called by a very specific thread after all). Am I missing something?

Update: I want to stress that I know what synchronized (this) does, because some comments below seem to suggest I don't. What I don't understand is why it was used in the above code fragment, which seems unnecessary.

onReceive() will not always be called on a UI thread. If BroadcastReceiver is registered using an overload of registerReceiver() which accepts a Handler scheduler param, then onReceive() callback will be executed on a thread, that handler has been attached to. From docs :

Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter, String broadcastPermission, Handler scheduler)

Register to receive intent broadcasts, to run in the context of scheduler . scheduler is a handler identifying the thread that will receive the Intent . If null, the main thread of the process will be used.

Nevertheless, particularly in the case outlined in the docs there is no need to wrap any code into a synchronized block, because the BroadcastReceiver is registered using standard registerReceiver(BroadcastReceiver, IntentFilter) overload, which is guarantees to fire onReceive() callback on UI thread.

I think that's merely a showcase code, that demonstrates how to correctly write an onReceive() implementation, taking care of all the edge cases. If the author of that doc hadn't written synchronized block I wouldn't know, that it's possible to make onReceive() to be executed on a thread other than UI thread.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM