前提:1.耗时的工作不可以在主线程中进行.
2.Thread子线程不能操作UI界面上的View,会报错.
这种情况下,Handler这种能操作UI界面的线程就诞生了.
handler.sendEmptyMessage(0);//发送消息到handler
handleMessage接受来自sendEmptyMessage的信息并做处理;
通常用于被重写;
public void handleMessage(Message msg) { switch(msg.what){ case 0://更细下载进度 process += 1; text.setText("下载" + process + "%");//在主线程中更新UI界面 break; case 1://提示下载完成 text.setText("下载完成");//在主线程中更新UI界面 break; default: break; } }
既然有接受消息,那发送消息呢?
我目前总结了两个方法:
myHandler.obtainMessage(msg值, data).sendToTarget();//data处可以换位任何对象 //并在handleMessage中通过构建相应对象来接收data; //另一种传递信息的方法--发送空消息,只发送一条消息; myHandler.sendEmptyMessage(msg值);
关于线程的常识:
- UI线程:就是我们的主线程,系统在创建UI线程的时候会初始化一个Looper对象,同时也会创建一个与其关联的MessageQueue;
- Handler:作用就是发送与处理信息,如果希望Handler正常工作,在当前线程中要有一个Looper对象
- Message:Handler接收与处理的消息对象
- MessageQueue:消息队列,先进先出管理Message,在初始化Looper对象时会创建一个与之关联的MessageQueue;
- Looper:每个线程只能够有一个Looper,管理MessageQueue,不断地从中取出Message分发给对应的Handler处理!
我见过的获取looper的两种方法:
第一种:
1 )直接调用Looper.prepare()方法即可为当前线程创建Looper对象,而它的构造器会创建配套的MessageQueue;
2 )创建Handler对象,重写handleMessage( )方法就可以处理来自于其他线程的信息了!
3 )调用Looper.loop()方法启动Looper
第二种:
1)自己做一个继承自Handler的类MyHandler,在其构造方法中设置(looper参数)
private class MyHandler extends Handler { MyHandler(Looper looper) { super(looper); } }
然后生造一个HandlerThread,构建MyHandler的时候looper参数设为HandlerThread.getlooper();
HandlerThread:内置了looper的Thread;
HandlerThread myThread = new HandlerThread("myHandler"); myThread.start(); MyHandler myHandler = new MyHandler(myThread.getLooper());