写在前面的话
1、参考自网络。
2、内容如果有不对的,希望可以指出或补充。
3、巩固内容。
一、概述
Handler(消息处理器):是Android提供的可以发送和处理主线程、子线程(耗时操作)间通讯和消息的一套消息处理机制。每个Handler都有一个单独的线程和对应(会默认绑定)的消息队列(MessageQueue-由Looper(按消息的先后顺序遍历)管理)。主要应用于更新UI
。
二、使用
一个线程对应一个Looper,一个Looper对应一个消息队列,一个消息队列可以对用多个Message。但是一个消息只能让一个handler来处理。
(一)发送消息
public class Test extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.test3);
/**发送消息的方法:
* sendMessage(Message msg) //立即发送信息到消息队列
* sendMessageAtFrontOfQueue(Message msg) //同上一个且是放在队列的最前面
* sendMessageDelayed(Message msg, long uptimeMillis) //指定延时多少毫秒后发送
* sendMessageAtTime(Message msg,long when) //指定什么时候发送
* //发送空消息
* sendEmptyMessage(int what)
* sendEmptyMessageDelayed(int what, long uptimeMillis)
* sendEmptyMessageAtTime(int what, long when)
* //post方法--run中的操作和主线程处于同一个线程,所以可以直接在非UI线程中更新UI
* post(Runnable r) //其实就是生成一个what为0的Message-》Runnable遇到没有运行的问题,是因为调用Handler.removeMessage()时,what参数传的0,导致Runnable所在的Message被remove了
* postAtFrontOfQueue(Runnable r)
* postDelayed(Runnable r, long uptimeMillis)
* postAtTime(Runnable,long)*/
//主线程中============================
//主线程->主线程发送消息
//1、携带数据
Bundle bundle = new Bundle();
bundle.putString("test", "传递一条测试信息");//参数2:消息内容
//2、建议使用Message.obtain() --》因为是从一个可回收的对象池中获取Message对象,避免了重复创建
Message message = Message.obtain(); // 实例化消息对象
message.setData(bundle);
message.what = 1;//消息标识
//3、创建静态内部类-调用
MyHandler myHandler = new MyHandler(this);
//5、发送数据
myHandler.sendMessage(message);
}
//3、创建静态内部类
private static class MyHandler extends Handler {
持有弱引用Activity,回收时会被回收掉-避免内存泄漏
private final WeakReference<Test> mTest;
public MyHandler(Test test) {
mTest = new WeakReference<Test>(test);
}
@Override
//4、接收消息
public void handleMessage(Message msg) {
super.handleMessage(msg);//处理消息
if (msg.what == 1) {
Bundle bundle = msg.getData();
String data = bundle.getString("test");//与bundle的参数1一致
Log.i("测试",data);
}
}
}
}
如下:
(二)处理消息
在子线程
(被Thread所包含的)中使用handler(handler的实例是在子线程中创建的),需要自己创建一个Looper对象(调用Looper.prepare()创建,另还需调用一个Looper.loop()启动)。
public class Test extends AppCompatActivity {
private TextView testHandler;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.test3);
//获取控件
testHandler = findViewById(R.id.test_handler);
//创建子线程
// 子线程->主线程,更新ui
new Thread(new Runnable() {
@Override
public void run() {
//创建Looper
Looper.prepare();
//创建handler实例
Handler myHandler = new Handler(){
@Override
public void handleMessage(Message msg) {
testHandler.setText("测试更改UI");
}
};
//发送消息-必有
myHandler.sendEmptyMessage(1);
//启动Looper
Looper.loop();
}
}).start();//启动线程
}
}
如下: