我正在阅读有关如何编程Android与USB配件通信的this page。其中一个步骤涉及注册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)
?将在UI线程上调用onReceive()
并将其调用。这段代码似乎没有触及其他线程可以访问的任何数据,除非对象accessory
计数(并且页面上没有任何暗示它的内容)。
我在网上搜索过,似乎没有太多强调onReceive()
中的线程安全性(毕竟它是由非常具体的线程调用的)。我错过了什么吗?
更新:我想强调我知道synchronized (this)
的作用,因为下面的一些评论似乎暗示我不会。我不明白为什么在上面的代码片段中使用了它,这似乎是不必要的。
答案 0 :(得分:0)
onReceive()
。如果BroadcastReceiver
使用接受registerReceiver()
参数的Handler scheduler
重载进行注册,则会在一个线程上执行onReceive()
回调,该处理程序已附加到该线程。来自docs:
Intent registerReceiver(BroadcastReceiver receiver, IntentFilter filter, String broadcastPermission, Handler scheduler)
注册以接收意图广播,以在调度程序的上下文中运行。 scheduler 是一个标识将接收
Intent
的线程的处理程序。如果为null,则将使用该进程的主线程。
尽管如此,特别是在文档中概述的情况下,不需要将任何代码包装到synchronized
块中,因为BroadcastReceiver
是使用标准registerReceiver(BroadcastReceiver, IntentFilter)
重载注册的,这是保证在UI线程上触发onReceive()
回调。
我认为这只是一个展示代码,它演示了如何正确编写onReceive()
实现,处理所有边缘情况。如果该文档的作者没有编写synchronized
块我不知道,可以使onReceive()
在UI线程以外的线程上执行。