📅  最后修改于: 2023-12-03 15:40:07.487000             🧑  作者: Mango
如果你是Android开发者,很可能会遇到这个异常:
android.os.NetworkOnMainThreadException
这个异常的意思是“在主线程上进行了网络操作”,即在UI线程上进行了涉及到网络请求的操作,这会导致UI线程被阻塞,造成卡顿等不良用户体验。
为了避免这个问题,在Android中一般都会使用异步方式进行网络请求,比如使用AsyncTask、Handler、Thread等。
但是,在使用这些异步操作时,会遇到另一个异常:
java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
这个异常的意思是“在线程中创建Handler时未调用Looper.prepare()”,即在非UI线程中创建Handler时,必须先调用Looper.prepare()方法,然后再创建Handler。否则,就会导致上述异常的抛出。
那么,为什么要使用Looper和Handler呢?
在Android中,每个线程都拥有自己的Message Queue(消息队列)和Looper(消息循环器),用于处理消息事件。而Handler则是用于向Message Queue发送消息,并且处理消息回调的机制。
在UI线程中,系统自动完成Looper和Handler的初始化,因此我们可以直接使用Handler来处理消息事件。但是,在非UI线程中,由于缺少Looper和Handler,我们需要手动初始化Looper,并创建Handler。
下面是一个使用Handler进行异步网络请求的示例代码:
public class NetworkTask implements Runnable {
@Override
public void run() {
// 初始化Looper
Looper.prepare();
// 创建Handler
Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
// 在这里处理消息事件
}
};
// 执行网络请求
// ...
// 发送消息到Message Queue中
handler.sendMessage(msg);
// 释放Looper
Looper.loop();
}
}
在上述代码中,我们先调用了Looper.prepare()方法来初始化Looper,然后创建了Handler,并在处理完网络请求后,向Message Queue发送了一个消息。最后,我们通过调用Looper.loop()方法来启动消息循环器,实现异步处理网络请求的目的。
总结一下,使用Looper和Handler进行异步处理时,必须保证在非UI线程中先调用Looper.prepare()方法来初始化Looper,然后再创建Handler。否则,就会出现“java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()”这样的异常。
在Android开发中,正确使用Looper和Handler机制,可以在保证UI线程流畅的同时,完成异步处理任务。