目录
一、为什么使用多线程
Android中主线程不能执行耗时操作、不能访问网络等。这些动作会导致主线程被阻塞,容易引起ANR(Application no response)异常。
所以必须把访问网络、耗时操作等放入到子线程中执行。Android的主线程(UI线程)是线程不安全的,所以当各个子线程获得数据之后不能直接修改UI,必须把修改UI的权利交给主线程。
二、异步消息处理机制——Handler
Android中的异步消息处理主要由4个部分组成:Message、Handler、MessageQueue和Looper。
- Looper
每一个线程只有一个Looper对象。每个线程在初始化Looper之后,Looper会维护好该线程的MessageQueue。MessageQueue用来存放Handler发送的Message,并处理MessageQueue中的Message。
当我们在主线程创建Handler时,它就会跟主线程唯一的Looper绑定,从而我们使用Handler在子线程发消息时,最终也是在主线程处理,达到了异步的效果。
非主线程没有loop对象,所以要调用Looper.prepare()方法。 - MessageQueue
MessageQueue是一个消息队列,用来存放Handler发送的消息。每个线程最多只有一个MessageQueue。
MessageQueue通常都是由Looper来管理。 - Message
被传递和处理的数据。其中包含了消息ID,消息处理对象以及处理的数据等,由MessageQueue统一列队,终由Handler处理。
一个MessageQueue可以包括多个Message。
Message虽然也可以通过new来获取,但是通常使用Message.obtain()或Handler.obtainMessage()方法来从消息池中获得空消息对象,以节省资源。 - Handler
负责Message的发送及处理。使用Handler时,需要实现handleMessage(Message msg)方法来对特定的Message进行处理,例如更新UI等。
子线程中使用Handler的步骤:
new Thread(new Runnable() {
@Override
public void run() {
//1、为子线程创建一个Looper
Looper.prepare();
//2、创建Handler对象
Handler handler = new Handler() {
@Override
public void handleMessage(@NonNull Message msg) {
super.handleMessage(msg);
}
};
//3、调用Looper.loop()
//在线程中调用过Looper.loop()之后,后面不能再写代码,因为loop()内部是个死循环,后面的写的代码无法执行到。
Looper.loop();
}
}).start();
1、Handler类中常用方法
1)sendEmptyMessage(int what)
发送一条空消息
2)sendEmptyMessageDelayed(int what, long delayMillis)
在该方法内部首先将what封装成一个Message,同时调用sendMessageDelayed(msg, delayMillis)方法延迟发送一条消息
3)sendMessageDelayed(Message msg, long delayMillis)
表示延迟发送一条消息
4)sendMessageAtTime(Message msg, long uptimeMillis)
方法表示定时发送一条消息
5)handleMessage(Message msg)
对Handler发送来的消息进行处理
6)post(Runnable r)
发送一个子线程
7)postDelayed(Runnable r, long delayMillis)
延迟发送一个子线程
8)obtainMessage()
从消息池中获得一个消息
2、Message消息类中常用属性
arg1:用来存放整型数据
arg2:用来存放整型数据
obj:用来存放Object数据
what:用于指定用户自定义的消息代码,这样便于主线程接收后,根据消息代码不同而执行不同的相应操作
3、Handler造成内存泄漏
1)原因
private Handler handler =