onReceive() 回调中的同步块
synchronized block inside onReceive() callback
我正在阅读 this page 如何编程 Android 以与 USB 配件通信。其中一个步骤涉及注册一个 BroadcastReceiver
以获得用户的许可:
IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
registerReceiver(mUsbReceiver, filter);
其中 mUsbReceiver
定义为:
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);
}
}
}
}
};
令我不解的是为什么要用synchronized (this)
? onReceive()
将在 UI 线程上调用,仅此而已。这段代码似乎没有触及任何可能被其他线程访问的数据,除非对象 accessory
很重要(页面上没有任何内容表明它很重要)。
我在网上查了下,onReceive()
好像没有太强调线程安全(毕竟是很具体的线程调用的)。我错过了什么吗?
更新:我想强调我知道 synchronized (this)
的作用,因为下面的一些评论似乎表明我不知道。我不明白的是为什么在上面的代码片段中使用它,这似乎是不必要的。
onReceive()
不会总是在 UI 线程上调用。如果使用接受 Handler scheduler
参数的 registerReceiver()
的重载注册 BroadcastReceiver
,则 onReceive()
回调将在已附加该处理程序的线程上执行。来自 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.
然而,特别是在文档中概述的情况下,不需要将任何代码包装到 synchronized
块中,因为 BroadcastReceiver
是使用标准 registerReceiver(BroadcastReceiver, IntentFilter)
重载注册的,这是保证在 UI 线程上触发 onReceive()
回调。
我认为这只是一个展示代码,演示了如何正确编写 onReceive()
实现,处理所有边缘情况。如果该文档的作者没有写 synchronized
块我不知道,可以使 onReceive()
在 UI 线程以外的线程上执行。
我正在阅读 this page 如何编程 Android 以与 USB 配件通信。其中一个步骤涉及注册一个 BroadcastReceiver
以获得用户的许可:
IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
registerReceiver(mUsbReceiver, filter);
其中 mUsbReceiver
定义为:
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);
}
}
}
}
};
令我不解的是为什么要用synchronized (this)
? onReceive()
将在 UI 线程上调用,仅此而已。这段代码似乎没有触及任何可能被其他线程访问的数据,除非对象 accessory
很重要(页面上没有任何内容表明它很重要)。
我在网上查了下,onReceive()
好像没有太强调线程安全(毕竟是很具体的线程调用的)。我错过了什么吗?
更新:我想强调我知道 synchronized (this)
的作用,因为下面的一些评论似乎表明我不知道。我不明白的是为什么在上面的代码片段中使用它,这似乎是不必要的。
onReceive()
不会总是在 UI 线程上调用。如果使用接受 Handler scheduler
参数的 registerReceiver()
的重载注册 BroadcastReceiver
,则 onReceive()
回调将在已附加该处理程序的线程上执行。来自 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.
然而,特别是在文档中概述的情况下,不需要将任何代码包装到 synchronized
块中,因为 BroadcastReceiver
是使用标准 registerReceiver(BroadcastReceiver, IntentFilter)
重载注册的,这是保证在 UI 线程上触发 onReceive()
回调。
我认为这只是一个展示代码,演示了如何正确编写 onReceive()
实现,处理所有边缘情况。如果该文档的作者没有写 synchronized
块我不知道,可以使 onReceive()
在 UI 线程以外的线程上执行。