从零了解Android消息机制

本着深入浅出的原则,本文详细介绍了从线程到Handler消息传递机制的内容,中间多引用博客,如果不了解,还是要详细看下链接里面的内容,适合像我这种基础不扎实的同学学习下。

首先,废话下为什么要有异步任务:
如果在主线程(UI线程)操作一些耗时的操作容易造成卡顿,
Android 规定主线程中不可以做耗时操作(访问网络,操作数据库)

现在最基础的异步任务的使用方法:
1.使用Handler消息传递机制;
2.使用AsyncTask异步任务;

要是这时候你不熟悉实现多线程的方式,请狂点
java线程系列---Runnable和Thread的区别

结论:
实现方式是1.实现Runnable接口 2.继承Thread类
多线程肯定永远以实现Runnable接口为主
使用Runnable实现多线程可以达到资源共享目的
另外,Thread类也是Runnable亲儿子

要是这时候你不能随手写出Handler的实现方式,请狂点
Android Handler详细使用方法实例

用法:
1.将handler绑定到它所建立的线程中,简单粗暴没情趣

    //使用handler时首先要创建一个handler(UI线程)
    Handler handler = new Handler();

    //将线程接口立刻送到线程队列中
    handler.removeCallbacks(update_thread);

    Runnable update_thread = new Runnable()
    {
        public void run()
        {
            //UI操作
        }
    };
    handler.post(update_thread);
    //将接口从线程队列中移除

2.handler的消息队列机制,慢条斯理前戏足

    // 调用:
    update_progress_handler.post(update_thread);

    //创建一个handler,内部完成处理消息方法
    Handler update_progress_handler = new Handler()
    {
        @Override
        public void handleMessage(Message msg) {
            // UI线程
            // msg.arg1 = "bilibili"
        }
    };

    Runnable update_thread = new Runnable()
    {
        public void run() {
            Message msg = update_progress_handler.obtainMessage();
            //把消息发送到消息队列中,msg对应handleMessage的入参
            msg.arg1 = "bilibili";
            update_progress_handler.sendMessage(msg);
        }
    };

    //移除
    update_progress_handler.removeCallbacks(update_thread);

3.自己看链接吧...

handler.sendMessage(msg) 和 handler.post(Runnable) 都知道什么情况下用了,接下来就是硬菜了

请狂点:
Android 异步消息处理机制 让你深入理解 Looper、Handler、Message三者关系

结论

1、首先Looper.prepare()在本线程中保存一个Looper实例,然后该实例中保存一个MessageQueue对象;因为Looper.prepare()在一个线程中只能调用一次,所以MessageQueue在一个线程中只会存在一个。
2、Looper.loop()会让当前线程进入一个无限循环,不端从MessageQueue的实例中读取消息,然后回调msg.target.dispatchMessage(msg)方法。
3、Handler的构造方法,会首先得到当前线程中保存的Looper实例,进而与Looper实例中的MessageQueue想关联。
4、Handler的sendMessage方法,会给msg的target赋值为handler自身,然后加入MessageQueue中。
5、在构造Handler实例时,我们会重写handleMessage方法,也就是msg.target.dispatchMessage(msg)最终调用的方法

还有需要注意的,因为最终调用的方法都是这个

public void dispatchMessage(Message msg) {  
      if (msg.callback != null) { 
          handleCallback(msg);  
      } else {  
          if (mCallback != null) {  
              if (mCallback.handleMessage(msg)) {  
                  return;  
              }  
          }  
          handleMessage(msg);  
      }  
  } 

分发消息流程:

当Message的msg.callback不为空时,则回调方法msg.callback.run();
当Handler的mCallback不为空时,则回调方法mCallback.handleMessage(msg);
最后调用Handler自身的回调方法handleMessage(),该方法默认为空,Handler子类通过覆写该方法来完成具体的逻辑。

消息分发的优先级:

Message的回调方法:message.callback.run(),优先级最高;
Handler中Callback的回调方法:Handler.mCallback.handleMessage(msg),优先级仅次于1;
Handler的默认方法:Handler.handleMessage(msg),优先级最低。

对于很多情况下,消息分发后的处理方法是第3种情况,即Handler.handleMessage(),一般地往往通过覆写该方法从而实现自己的业务逻辑。

懵懵懂懂是嘛?换个方向给你说一遍,补充下内容,能更好的了解整个过程
Android消息机制的原理剖析—闭环总结

结论

(a)MessageQueue和Looper:一对一关系,MessageQueue的创建后放置在Looper中。
(b)Looper和线程:一个线程只有一个,创建之后保存在ThreadLocal中,想要获取ThreadLocal.get()即可。
(c)Handler和Looper:Handler创建时候,从ThreadLocal中获取Looper,Handler变量指向这个Looper,Handler和Looper绑定。
(d)Message和Handler:Handler发送Message时候,Message的target属性指向这个Handler,也是这个Handler来分发处理这个Message
(e)消息池:only one,所有线程共享。

现在Android的消息机制都玩的溜了,不过对于偶尔用到一次用到就要考虑什么异步消息处理机制,还要专门使用一个Handler来发送和接收消息,就好比每次哄好了好不容易脱光了衣服还要先洗澡一样...

这个时候,就必须要学会AsyncTask了
Android AsyncTask完全解析,带你从源码的角度彻底理解

强突:

 * 执行次序    执行时机        方法名称           调用方
 *  1        异步任务执行前   onPreExecute      UI线程
 *  2        异步任务执行中   doInBackground    后台线程
 *  3        异步任务执行中   publishProgress   后台线程
 *  4        异步任务执行中   onProgressUpdate    UI线程
 *  5        异步任务执行后   onPostExecute       UI线程

使用:

private class MyTask extends AsyncTask<String, Integer, String> {
        @Override
        protected void onPreExecute() {
            //onPreExecute方法用于在执行后台任务前做一些UI操作
        }

        //doInBackground方法内部执行后台任务,不可在此方法内修改UI
        @Override
        protected String doInBackground(String... params) {
            //doInBackground方法内部执行后台任务,不可在此方法内修改UI
            // 后台线程向UI线程发布进度状态
            publishProgress(i);
            return null;
        }

        @Override
        protected void onProgressUpdate(Integer... progresses) {
            //onProgressUpdate方法用于更新进度信息
        }

        @Override
        protected void onPostExecute(String result) {
            //onPostExecute方法用于在执行完后台任务后更新UI,显示结果
        }

        @Override
        protected void onCancelled() {
            //onCancelled方法用于在取消执行中的任务时更改UI
        }
    }

调用:

               //注意每次需new一个实例,新建的任务只能执行一次,否则会出现异常
                mTask = new MyTask();
                mTask.execute();

                //取消一个正在执行的任务,onCancelled方法将会被调用
                mTask.cancel(true);

结论:

AsyncTask也是使用的异步消息处理机制,只是做了非常好的封装

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,236评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,867评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,715评论 0 340
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,899评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,895评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,733评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,085评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,722评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,025评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,696评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,816评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,447评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,057评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,009评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,254评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,204评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,561评论 2 343

推荐阅读更多精彩内容