Android-线程通讯设计模式-Handler消息模型
Android-线程通讯设计模式-Handler消息模型
问题思考:
1) Android中的工作线程获取数据以后如何传递给主线程?
例如:
例如工作线程通过网络下载一张图片,通过主线程将图片更新到页面上。
所有的耗时操作在工作线程,工作线程不能操作UI
2) Android 中主线程的数据如何传递给工作线程?
例如:
主线程将要下载的文件的名字传递给工作线程。
记住:工作线程是不能更新UI的
目的:尽量不要去阻塞主线程,安卓中的UI运行在主线程。
3)SendMessage与PostMessage的区别:
前者同步,后者异步。
SendMessage发送消息后会等对方处理完这个消息后才会继续!
PostMessage则将消息发送出去后就会继续!
所以注意,不要通过PostMessage传递临时变量指针,应该很可能消息被处理时该变量已经销毁,这时访问就会出错
4)handleMessage与dispatchMessage处理消息的区别?
handleMessage处理消息在主线程中
dispatchMessage处理消息相当新开了一个线程中
用SendMessage替换DispatchMessage不会有问题,但是效率没有DispatchMessage高
但是用DispatchMessage替换SendMessage却不行!
dispatchMessage是新开了一个线程,而sendMessage是在主线程,所以更新UI的时候报错了,这也应证了安卓只能在主线程更新UI这一情况了。
Android中线程通讯底层消息模型
Handler给哪个线程发消息,就关联哪个线程的looper(双向关联!)
注:此章是为了个人能更好的理解Android底层机制
Android中线程之间进行数据传递通常要借助消息模型,在这个消息模型中会设计到如下几个对象:
-
Message(消息对象):数据的载体
-
MessageQueue(消息队列):存储多个消息对象
-
Looper(迭代器对象):迭代消息队列
-
Handler(消息处理对象):发送,处理消息
简单案例不涉及主线程与工作线程!
class Message{ Object obj; @Override public String toString() { return "Message [obj=" + obj + "]"; } } class MessageQueue{ private BlockingQueue<Message> queue= new ArrayBlockingQueue<>(10); public void put(Message msg){//放消息 try{ queue.put(msg); }catch(Exception e){} } public Message take(){//取消息 try { return queue.take(); } catch (Exception e) { e.printStackTrace(); return null; } } } class Looper{ private MessageQueue mq; //Looper关联MessageQueue(MessageQueue的生命周期随looper变化而变化,这是强聚合) //Looper关联Handler(通过set等方法的是低聚合) //注:能从Looper中关联Handler,也能从Handler中关联looper,这是双向关联! private Handler handler; public void setHandler(Handler handler) { this.handler = handler; } public MessageQueue getMq() { return mq; } boolean flag=true; public Looper(){ mq=new MessageQueue();//强聚合(组合) } public void loop(){ while(flag){ //迭代消息队列 Message msg=mq.take(); //调用handler方法处理消息 handler.handleMessage(msg); } } } class Handler{ //Hanlder关联looper(has a),获取消息队列 private Looper looper; public Handler(Looper looper){ this.looper=looper; looper.setHandler(this); } //Handler与Message的关系是use a public void sendMessage(Message msg){ //将消息存储到消息队列 looper.getMq().put(msg); } public void handleMessage(Message msg){ //处理消息队列中的消息 System.out.println(msg); } } public class TestMsg { public static void main(String[] args) { //消息对象 Message msg1=new Message(); msg1.obj="helloworld"; //迭代器对象(此对象创建时会创建消息队列) Looper looper=new Looper(); Handler h=new Handler(looper); h.sendMessage(msg1); Message msg2=new Message(); msg2.obj="gsd1504"; h.sendMessage(msg2); looper.loop(); } }
主线程与工作线程配合案例
class Message{ Object obj; @Override public String toString() { return "Message [obj=" + obj + "]"; } } class MessageQueue{ private BlockingQueue<Message> queue= new ArrayBlockingQueue<>(10); public void put(Message msg){//放消息 try{ queue.put(msg); }catch(Exception e){} } public Message take(){//取消息 try { return queue.take(); } catch (Exception e) { e.printStackTrace(); return null; } } } class Looper{ private MessageQueue mq; private Handler handler; public void setHandler(Handler handler) { this.handler = handler; } public MessageQueue getMq() { return mq; } boolean flag=true; public Looper(){ mq=new MessageQueue();//强聚合(组合) } public void loop(){ while(flag){ //迭代消息队列 Message msg=mq.take(); //调用handler方法处理消息 handler.handleMessage(msg); } } } class Handler{ private Looper looper; public Handler(Looper looper){ this.looper=looper; looper.setHandler(this); } public void sendMessage(Message msg){ //将消息存储到消息队列 looper.getMq().put(msg); } public void handleMessage(Message msg){ //处理消息队列中的消息 System.out.println(msg); } } public class TestMsg { static Looper looper; /**主线程给工作线程发消息*/ public static void main(String[] args) { //消息对象 Message msg1=new Message(); msg1.obj="helloworld"; //迭代器对象(此对象创建时会创建消息队列) new Thread(){ public void run() { //looper共享数据集加锁 synchronized (TestMsg.class) { looper=new Looper(); TestMsg.class.notify();//类对象 } looper.loop(); }; }.start(); synchronized (TestMsg.class) { //Hanlder关联那个线程的looper,就给哪个线程发消息 //也就是主线程给工作线程发消息 if(looper==null)try{TestMsg.class.wait();}catch(Exception e){} Handler h=new Handler(looper); h.sendMessage(msg1); } } } //给哪个线程发消息就让handler关联哪个线程的looper 提取类封装拿到looper案例
HandlerThread类:
public class HandlerThread extends Thread{ Looper looper; @Override public void run() { synchronized (this) { looper=new Looper(); this.notify(); } looper.loop(); } public Looper getLooper(){ synchronized (this) { if(looper==null) try{this.wait();}catch(Exception e){e.printStackTrace();} return looper; } } //一个方法运行在哪个线程取决于此方法在哪个线程被调用的 }
TestMsg类
class Message{ Object obj; @Override public String toString() { return "Message [obj=" + obj + "]"; } } class MessageQueue{ private BlockingQueue<Message> queue= new ArrayBlockingQueue<>(10); public void put(Message msg){//放消息 try{ queue.put(msg); }catch(Exception e){} } public Message take(){//取消息 try { return queue.take(); } catch (Exception e) { e.printStackTrace(); return null; } } } class Looper{ private MessageQueue mq; private Handler handler; public void setHandler(Handler handler) { this.handler = handler; } public MessageQueue getMq() { return mq; } boolean flag=true; public Looper(){ mq=new MessageQueue();//强聚合(组合) } public void loop(){ while(flag){ //迭代消息队列 Message msg=mq.take(); //调用handler方法处理消息 handler.handleMessage(msg); } } } class Handler{ private Looper looper; public Handler(Looper looper){ this.looper=looper; looper.setHandler(this); } public void sendMessage(Message msg){ //将消息存储到消息队列 looper.getMq().put(msg); } public void handleMessage(Message msg){ //处理消息队列中的消息 System.out.println(msg); } } public class TestMsg { /**主线程给工作线程发消息*/ public static void main(String[] args) { //消息对象 Message msg1=new Message(); msg1.obj="helloworld"; //迭代器对象(此对象创建时会创建消息队列) HandlerThread ht=new HandlerThread(); ht.start(); System.out.println("start"); Handler h=new Handler(ht.getLooper()); System.out.println("h="+h); h.sendMessage(msg1); } } //给哪个线程发消息就让handler关联哪个线程的looper