前言
什么是子线程?什么是主线程?为什么需要使用Handler?子线程和主线程怎么通信?
主线程是我们程序进程在创建的时候,调用ActivityThread的main入口,Looper.prepareMainLooper创建消息队列,接受activity 、window等消息,包括视图渲染。
我们知道Android的界面绘制是1秒钟60帧,也就是1000/60=16ms绘画一帧,如果我们有一些耗时操作,比如下载图片(花费2s),如果我们放在主线程下载,会阻塞主线程,让主线程不能处理消息2s,反映到界面就是程序无响应2s。所以在这种情况下,我们需要创建一个子线程,等子线程的图片下载完之后再通知主线程,把图片设置到图片视图上。
那么子线程和主线程怎么通信呢?这就要用我们的Handler了,这篇文章主要是讲怎么使用Handler,子线程和主线程通信的底层原理我会单独写一篇文章分析,走进源码,Android面试最常见Handler、Looper、Message问题总结与解答
【转载请注明出处:最简单的Handler、Looper、Message使用指南一(附github源码) CSDN 王智博】
源码下载
github:https://github.com/samwangzhibo/LoveStudy (不会使用github导入代码的同学,戳这)
举个栗子
比如我们要实现在主线程打印子线程传递过来数据这个需求,我们实现一个子线程一直发送数据,主线程获取数据并且用TextView打印出子线程传过来的数据。
Let do it!
第一步我们创建一个一直发送数据的子线程
class SendThread extends Thread {
int num = 0;
boolean isEnd = false;
private final int DURATION_SLEEP = 1000;
void setEnd(boolean end) {
isEnd = end;
}
@Override
public void run() {
super.run();
while (!isEnd) {
mainHandler.sendMessage(Message.obtain(mainHandler, WHAT_MODIFY_TV, num++));
try {
//不释放资源 休眠
Thread.sleep(DURATION_SLEEP);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
其中最重要的是Handler发送数据的方法,sendMessage(Message msg)
第二步在主线程中获取数据并且展示
Handler mainHandler = new Handler(Looper.getMainLooper()) {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case WHAT_MODIFY_TV:
tvReciver.setText("接受子线程传递的参数:" + msg.obj);
break;
default:
}
}
};
其中子线程传递过来的数据是存放在Handler handleMessage中的Message.obj里面
总结
1.在主线程(需要获取数据的线程)创建Handler
Handler mainHandler = new Handler(Looper.getMainLooper())
2.在子线程发送数据,(num++便是携带的数据)
mainHandler.sendMessage(Message.obtain(mainHandler, WHAT_MODIFY_TV, num++));
3.重写Handler的handleMessage方法,获取子线程的数据
public void handleMessage(Message msg) {
switch (msg.what) {
case WHAT_MODIFY_TV:
tvReciver.setText("接受子线程传递的参数:" + msg.obj);
break;
default:
}
}
扩展
如果想要看Handler为啥可以在主线程和子线程通信,请戳楼主的面试文章
走进源码,Android面试最常见Handler、Looper、Message问题总结与解答
源码下载
github:https://github.com/samwangzhibo/LoveStudy (不会使用github导入代码的同学,戳这)
全部代码
public class HandlerActivity extends Activity {
private static final int WHAT_MODIFY_TV = 100;
TextView tvReciver;
SendThread sendThread;
Handler mainHandler2 = new Handler();
Handler mainHandler = new Handler(Looper.getMainLooper()) {
@Override
public void handleMessage(Message msg) {
switch (msg.what) {
case WHAT_MODIFY_TV:
tvReciver.setText("接受子线程传递的参数:" + msg.obj);
break;
default:
}
}
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_handler);
tvReciver = findViewById(R.id.tv_receiver);
//开启一个子线程,一直朝主线程发送数据
sendThread = new SendThread();
sendThread.start();
}
@Override
protected void onDestroy() {
super.onDestroy();
//退出时候切记 关闭线程 回收资源 !!!!
sendThread.setEnd(true);
}
class SendThread extends Thread {
int num = 0;
boolean isEnd = false;
private final int DURATION_SLEEP = 1000;
void setEnd(boolean end) {
isEnd = end;
}
@Override
public void run() {
super.run();
while (!isEnd) {
mainHandler.sendMessage(Message.obtain(mainHandler, WHAT_MODIFY_TV, num++));
try {
//不释放资源 休眠
Thread.sleep(DURATION_SLEEP);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}