Android消息队列机制

相关文章
Android消息队列机制
IntentService中的耗时操作

C]
文章将带你理解 Looper、Handler、Message三者的关系。

一、基本用法

延时应用

定时器应用

//一个定时器
    private Handler handler = new Handler();  
  
    private Runnable myRunnable= new Runnable() {
       
        public void run() {
     
             
            if (run) {
     
                handler.postDelayed(this, 1000);  
                count++;  
            }  
            tvCounter.setText("Count: " + count);  

        }  
    }; 

//然后在其他地方调用

handler.post(myRunnable);

handler.post(myRunnable,time);
    new Thread(new Runnable() {
   
            @Override
            public void run() {
   
                //在子线程post一个Runnable对象
                handler.post(new Runnable() {
   
                    @Override
                    public void run() {
   
                        //这里是消息处理的方法
                        //这里运行在主线程。
                    }
                });
            }
        }).start();

一个线程发送消息,另外一个线程接收信息

   //在主线程创建一个Handler对象。
    //重写Handler的handleMessage方法,这个就是接收并处理消息的方法。
    Handler handler = new Handler(){
   
        @Override
        public void handleMessage(Message msg) {
   
            //msg就是子线程发送过来的消息。
        }
    };

    //开启一个子线程
    new Thread(new Runnable() {
   
            @Override
            public void run() {
   
                //在子线程发送一个消息。
                Message msg = new Message();
                handler.sendMessage(msg);
            }
        }).start();

 //声明Handler;
    Handler handler;
    new Thread(new Runnable() {
   
        @Override
        public void run() {
   
        //创建当前线程的Looper
            Looper.prepare();
            //在子线程创建handler对象
            handler = new Handler() {
   
                @Override
                public void handleMessage(Message msg) {
   
                //这里是消息处理,它是运行在子线程的
                }
           };
           //开启Looper的消息轮询
           Looper.loop();
       }
   }).start();

   mBanner.setOnClickListener(new View.OnClickListener() {
   
       @Override
       public void onClick(View v) {
   
       //在主线程发送一个消息到子线程
           Message msg = new Message();
           handler.sendMessage(msg);
       }
   });
//退出轮询
	Looper.myLooper().quit();
    Looper.myLooper().quitSafely();

获取主线程

Looper.getMainLooper()是获取主线程消息队列。

   new Thread(new Runnable() {
   
        @Override
        public void run() {
   
            //获取主线程的Looper
            Looper looper = Looper.getMainLooper();
            //用主线程的Looper创建Handler
            handler = new Handler(looper) {
   
                @Override
                public void handleMessage(Message msg) {
   
                //这里是运行在主线程的
                }
            };
        }
    }).start();

取消某个消息

handler.removeCallbacksAndMessages(null); //取消所有的回调方法和message

二、原理

Message

\frameworks\base\core\java\android\os\Message.java

public final class Message implements Parcelable {
   
 /**
     * User-defined message code so that the recipient can identify
     * what this message is about. Each {@link Handler} has its own name-space
     * for message codes, so you do not need to worry about yours conflicting
     * with other handlers.
     */
    public int what;

    /**
     * arg1 and arg2 are lower-cost alternatives to using
     * {@link #setData(Bundle) setData()} if you only need to store a
     * few integer values.
     */
    public int arg1;

    /**
     * arg1 and arg2 are lower-cost alternatives to using
     * {@link #setData(Bundle) setData()} if you only need to store a
     * few integer values.
     */
    public int arg2;

    /**
     * An arbitrary object to send to the recipient.  When using
     * {@link Messenger} to send the message across processes this can only
     * be non-null if it contains a Parcelable of a framework class (not one
     * implemented by the application).   For other data transfer use
     * {@link #setData}.
     *
     * <p>Note that Parcelable objects here are not supported prior to
     * the {@link android.os.Build.VERSION_CODES#FROYO} release.
     */
    public Object obj;

    /**
     * Optional Messenger where replies to this message can be sent.  The
     * semantics of exactly how this is used are up to the sender and
     * receiver.
     */
    public Messenger replyTo;

    /**
     * Optional field indicating the uid that sent the message.  This is
     * only valid for messages posted by a {@link Messenger}; otherwise,
     * it will be -1.
     */
    public int sendingUid = -1;

    /** If set message is in use.
     * This flag is set when the message is enqueued and remains set while it
     * is delivered and afterwards when it is recycled.  The flag is only cleared
     * when a new message is created or obtained since that is the only time that
     * applications are allowed to modify the contents of the message.
     *
     * It is an error to attempt to enqueue or recycle a message that is already in use.
     */
    /*package*/ static final int FLAG_IN_USE = 1 << 0;

    /** If set message is asynchronous */
    /*package*/ static final int FLAG_ASYNCHRONOUS = 1 << 1;

    /** Flags to clear in the copyFrom method */
    /*package*/ static final int FLAGS_TO_CLEAR_ON_COPY_FROM = FLAG_IN_USE;

    /*package*/ int flags;

    /*package*/ long when;

    /*package*/ Bundle data;

    /*package*/ Handler target;

    /*package*/ Runnable callback;

    // sometimes we store linked lists of these things
    /*package*/ Message next;

    private static final Object sPoolSync = new Object();
    private static Message sPool;
    private static int sPoolSize = 0;

    private static final int MAX_POOL_SIZE = 50;

    private static boolean gCheckRecycle = true;
    
    public static Message obtain() {
   
        synchronized (sPoolSync) {
   
        	//如果消息池里面有空闲的消息可以用,则用消息池里面的。
            if (sPool != null) {
   
            	//当前这条信息取自消息池里面的复用
                Message m = sPool;
                //取出消息池的下一条未用信息
                sPool = m.next;
                //当前这条链路掐断
                m.next = null;
                m.flags = 0; // clear in-use flag
                //消息池内信息减1
                sPoolSize--;
                return m;
            }
        }
        return new Message();
    }
    /**
     * Same as {@link #obtain()}, but copies the values of an existing
     * message (including its target) into the new one.
     * @param orig Original message to copy.
     * @return A Message object from the global pool.
     */
    public static Message obtain(Message orig) {
   
        Message m = obtain();
        m.what = orig.what;
        m.arg1 = orig.arg1;
        m.arg2 = orig.arg2;
        m.obj = orig.obj;
        m.replyTo = orig.replyTo;
        m.sendingUid = orig.sendingUid;
        if (orig.data != null) {
   
            m.data = new Bundle(orig.data);
        }
        m.target = orig.target;
        m.callback = orig.callback;

        return m;
    }
    
    /**
     * Same as {@link #obtain()}, but sets the value for the <em>target</em> member on the Message returned.
     * @param h  Handler to assign to the returned Message object's <em>target</em> member.
     * @return A Message object from the global pool.
     */
    public static Message obtain(Handler h) {
   
        Message m = obtain();
        m.target = h;

        return m;
    }

    /**
     * Same as {@link #obtain(Handler)}, but assigns a callback Runnable on
     * the Message that is returned.
     * @param h  Handler to assign to the returned Message object's <em>target</em> member.
     * @param callback Runnable that will execute when the message is handled.
     * @return A Message object from the global pool.
     */
    public static Message obtain(Handler h, Runnable callback) 
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值