网站首页被k怎么办,网站建设的好处,推广链接制作软件,网络营销策划方案1.消息循环机制 Handler是Android提供的用于发送、接收和处理Message或Runnable对象的类,它与Message、MessageQueue、Looper类以及当前线程实现了一个消息循环机制,用于实现消息的异步加载和处理。
整个异步消息处理流程简易图: ①Message:消息体,用于装载需要发送的对…1.消息循环机制 Handler是Android提供的用于发送、接收和处理Message或Runnable对象的类,它与Message、MessageQueue、Looper类以及当前线程实现了一个消息循环机制,用于实现消息的异步加载和处理。
整个异步消息处理流程简易图: ①Message:消息体,用于装载需要发送的对象。 一般使用Message.obtain()或Handler.obtainMessage()获取Message实例对象,而不直接使用new Message()。Message.obtain()会从消息池中获取一个Message对象,如果消息池中是空的才会new一个新Message,这样有利于消息资源的利用。 ②Handler:直接继承自Object,一般是在子线程中发送Message或Runnable对象到消息队列中;然后在主线程中接收并处理从消息队列分发出来的Message对象。 ③MessageQueue:消息队列,内部使用的是单链表结构(插入和删除效率比较高)。它由对应的Looper对象创建,并由Looper对象管理。 每个线程只会有一个消息队列。 ④Looper:不断从消息队列中取出消息进行分发。调用Looper.loop()方法后,就会进入到一个无限循环中,每当发现消息队列中存在一条消息,就将它取出并调用Handler的handleMessage()方法处理消息。 每个线程只会有一个Looper对象。
下面按照消息循环处理机制的步骤分别解析。
2.第一步:准备好要发送的消息Message Message类内部维护了一个Message对象池用于Message对象的复用,使用obtain()可以直接从对象池中获取Message对象,避免重新创建。 public final class Message implements Parcelable { //Message对象的几个重要参数 public int what; public int arg1; public int arg2; public Object obj; public long when; Handler target; Runnable callback; Message next;
public static final Object sPoolSync = new Object(); private static Message sPool; //对象池 private static int sPoolSize = 0; private static final int MAX_POOL_SIZE = 50; public static Message obtain() { synchronized (sPoolSync) { if (sPool != null) { Message m = sPool; sPool = m.next; m.next = null; m.flag = 0; //clear in-use flag sPoolSize --; return m; } } //若池内无消息,则还是用new创建 return new Message(); } } 如果消息池内有消息,则返回第一个消息实例,否则新建消息对象。 所以一般使用obtain()获取Message对象,避免每次都使用new重新分配内存,消耗更多的内存资源。
Message类中其他带参数的obtain()重载方法,都是先使用obtain()得到对象实例后再进行赋值操作。注意obtain( Handler h, Runnable callback)这个静态方法,因为涉及到Message的两个重要成员变量: public final class Message implements Parcelable { Handler target; Runnable callback; public static Message obtain(Handler h, Runnable callback) { Message m = obtain(); m.target = h; m.callback = callback; return m; } } 同样是赋值操作,其中target指向Message所关联的Handler。除了target还有一个callback,这个callback也是配合着Handler来发挥作用的。
总结Message: ①通常使用Message.obtain()方法获取Message对象实例; ②Message有两个重要的成员变量,分别为target 和callback,一个是Handler类型,一个是Runnable类型; ③Message有4个公开变量what、arg1、arg2、obj,可以存储消息进行传递; ④Message的对象池是一个链表,所以还有一个next成员变量,也是Message类型。
3.第二步:创建Handler对象 Handler在消息传递过程中扮演着重要的角色,是消息的主要处理者。Handler的主要作用就是发送、接收并处理消息。 Handler的构造方法: Handler() Handler(Callback callback) Handler(boolean async) Handler(Callback callback, boolean async) Handler(Looper looper) Handler(Looper looper, Callback callback) Handler(Looper looper, Callback callback, boolean async) 这些构造方法都是相继往下调用的,所以直接看最后一个方法: public class Handler { final Looper mLooper; final MessageQueue mQueue; final Callback mCallBack; final boolean mAsynchronous; public Handler(Looper looper, Callback callback, boolean async) { mLooper = looper; mQueue = looper.mQueue; mCallback = callback; mAsynchronous = async; } } Handler的这些构造方法里,如果looper不传值则会使用Looper.mylooper()获取当前线程的Looper实例;如果传值则使用传进来的looper对象。一般在子线程中使用Handler时才传此参数。
再看另外一个构造方法: public class Handler { public Handler(Callback callback,boolean async){ mLooper = Looper.myLooper(); //参数中没有传Looper,则使用当前线程的Looper对象 if (mLooper == null) { throw new RuntimeException(“Can’t create handler inside thread " + Thread.currentThread() + " that has not called Looper.prepare()”); } mQueue = mLooper.mQueue; //mQueue为Looper对象对应的消息队列 mCallback = callback; //接口回调 mAsynchronous = async; //是否为异步消息 }
public interface Callback { public boolean handleMessage(Message msg); } } 首先获取Handler实例所在线程的Looper对象。如果Looper不为空就获取Looper对应的消息队列,赋值给Handler的成员变量mQueue,然后设置Callback用于处理消息回调。
在一个线程中可以创建多个handler对象,这些handler都往这个线程的Looper中塞消息,Looper按照顺序去轮询到消息,进行处理。 比如在线程A中,可以使用线程B的handler发送消息,这个消息会发送到到线程B的消息队列中,线程B的handler通过其Looper在线程B中轮询消息。这个handler就像是线程B放出去的口子,谁向线程B发消息,就通过我来塞。
在子线程中声明的Handler是不能直接更新UI的,需要调用Handler相关的构造方法,传入主线程的Looper,这样创建的Handler实例才能进行UI的更新操作。
注意,子线程默认是没有开启Looper的,所以在子线程中创建Handler之前,必须先通过Looper.prepare()方法开启子线程的Looper,否则就会报异常: if (mLooper == null) { throw new RuntimeException(“Can’t create handler inside thread " + Thread.currentThread() + " that has not called Looper.prepare()”); } 创建了Handler对象,接下来就可以用Handler的sendMessage()方法来传递对象了。
总结Handler: (1)Handler有且只能绑定一个线程的Looper; (2)Handler把消息发送给Looper对应的消息队列MessageQueue中,然后等待处理。
Handler创建完成后,它负责把Message发送到消息队列mQueue,然后排队等待,Looper从消息队列将消息一个一个的取出来,然后通知消息对应的Handler去分发处理消息。
4.第三步:handler发送Message 第一步、第二步创建好了handler和Message对象,接下来就需要使用创建好的handler对象来发送该Message对象了。
Handler发送消息有两种方法:sendMessage()和postMessage()。
①首先看sendMessage()系列方法