当前位置: 代码迷 >> 综合 >> Can’t create handler inside thread that has not called Looper.prepare()
  详细解决方案

Can’t create handler inside thread that has not called Looper.prepare()

热度:20   发布时间:2024-01-11 12:23:18.0

问题:
最近在做一个使用SIP通话的客户端。在程序启动的时候要启动蓝牙设备,以连接蓝牙耳机等。

当在一个Thread中调用蓝牙初始化的方法时出现如下的错误:








publicstatic void init() {
if(ba == null) {
ba = BluetoothAdapter.getDefaultAdapter();
am = (AudioManager) Receiver.mContext.getSystemService(
Context.AUDIO_SERVICE);
}
}

Error Code:

12-30 11:48:21.577: W/System.err(25134): java.lang.RuntimeException: Can’t create handler inside thread that has not called Looper.prepare()
12-30 11:48:21.639: W/System.err(25134): at android.os.Handler.(Handler.java:121)
12-30 11:48:21.639: W/System.err(25134): at android.bluetooth.BluetoothAdapter$1.(BluetoothAdapter.java:853)
12-30 11:48:21.639: W/System.err(25134): at android.bluetooth.BluetoothAdapter.(BluetoothAdapter.java:852)
12-30 11:48:21.639: W/System.err(25134): at android.bluetooth.BluetoothAdapter.getDefaultAdapter(BluetoothAdapter.java:324)
12-30 11:48:21.639: W/System.err(25134): at org.xxxx.media.Bluetooth.init(Bluetooth.java:43)

分析:
报的是一个Android Looper的错误,从字面意思上看是没有调用Looper.prepare()方法。

1. Looper是什么?
Looper又是什么呢? ,其实Android中每一个Thread都跟着一个Looper,Looper可以帮助Thread维护一个消息队列。默认的Thread是没有Looper机制的,需要在线程中首先调用Looper.prepare()来创建消息队列,然后调用Looper.loop()进入消息循环。















classLooperThread extendsThread {
publicHandler mHandler;
publicvoid run() {
Looper.prepare();
mHandler =new Handler() {
publicvoid handleMessage(Message msg) {
// process incoming messages here
}
};
Looper.loop();
}
}

2. 为什么在Thread内调用初始化Bluetooth的方法需要调用Looper.prepare()?
从现象上来看调用ba = BluetoothAdapter.getDefaultAdapter();应该在主线程中进行调用,不应该在工作线程中。
在工作线程中调用可能会由于没有消息队列的管理导致线程不同步。

3. 使用Handler是否可以解决问题,怎么使用?
在主线程中创建Handler,另外一个线程怎样把消息放入主线程的消息队列呢?
答案是通过Handle对象,只要Handler对象以主线程的Looper创建,那么调用Handler的sendMessage等接口,将会把消息放入队列都将是放入主线程的消息队列。并且将会在Handler主线程中调用该handler的handleMessage接口来处理消息。

 

 

总结:每一个子线程默认没有Looper机制,而在android系统中消息队列是由Looper管理维护的,所有当创建消息的时候,必须有Looper的存在,但是主线程有自己默认的Looper。因为消息队列由Looper管理所致,所以要想发消息,必须有Looper。

  相关解决方案