-
背景
小编昨晚跟同学聊了很久,了解到其面试中的困惑,每当被问handler机制时就不知道怎么去说,哪怕他知道handler的作用。在这里呢,小编就用案例的形式带你深入了解handler。
-
案例
异步加载图片,在网上随便找了一张图片地址 http://p1.so.qhmsg.com/t01e2b20000369dbd11.jpg
-
核心代码
handler 实现线程间通讯,是因为共享了 looper 的内存,所以 handlerMessage( ) 运行在哪个线程由 looper 决定。而本章 new handler 默认拿的是主线程的 looper,因此运行在主线程。
主线程创建时,消息队列和轮询器对象就会被创建;
主线程中有一个消息轮询器looper,不断检测消息队列中是否有新消息,如果发现有新消息,自动调用此方法,注意此方法是在主线程中运行的;
Handler handler=new Handler(){
@Override
public void handleMessage(Message msg) {
switch (msg.what){
//7.把位图对象显示至imageview
case 1:
iv.setImageBitmap((Bitmap) msg.obj);
break;
case 2:
Toast.makeText(MainActivity.this,"请求失败!",Toast.LENGTH_SHORT).show();
break;
}
}};
因为网络交互属于耗时操作,如果网速很慢,代码会阻塞,所以网络交互的代码不能运行在主线程;
在子线程中往消息队列里发消息
new Thread(){
@Override
public void run() {
try {
//1.下载图片确定网址,将网址封装成url对象
URL url = new URL("http://p1.so.qhmsg.com/t01e2b20000369dbd11.jpg");
//2.获取客户端与服务器连接对象,此时还没有建立连接
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
//3.对连接对象进行初始化
conn.setRequestMethod("GET");//连接方式
conn.setConnectTimeout(3000);//连接超时
conn.setReadTimeout(3000);//读取超时
//4.发送请求,与服务器建立连接
conn.connect();
//响应码=200,说明请求成功
if (conn.getResponseCode()==200){
//5.获取服务器响应头里的流,流中的数据就是请求端的数据
InputStream is = conn.getInputStream();
//6.读取数据流里的数据,构造成位图对象
Bitmap bitmap = BitmapFactory.decodeStream(is);
Message msg=handler.obtainMessage();
//消息对象可以携带数据
msg.obj=bitmap;
msg.what=1;
//把消息发送至主线程的消息队列
handler.sendMessage(msg);
}else {
Message msg = handler.obtainMessage();
msg.what=2;
handler.sendMessage(msg);
}
} catch (Exception e) {
e.printStackTrace();
}
}}.start();
-
编译后截图
-
总结
其实handler机制很简单,一般就是用于主线程跟子线程之间的通信。比如,子线程不能更新UI,那么通过handler的sendMessage( )发送消息给主线程,而主线程在创建时,Message Queue(消息队列)和looper(轮询器对象)就会被创建,message就会放在Message Queue里,而Looper一旦发现Message Queue中有消息,就会把消息取出,然后把消息扔给Handler对象,Handler会调用自己的handleMessage方法来处理这条消息。