Android的消息机制主要是Handler的运行机制,而讲Handler的机制,又需要和MessageQueue和Looper结合。MessageQueue中文意思是消息队列,虽说叫队列,但是其内部结构并不是队列组成的,而是采用了单链表的形式来存储消息。MessageQueue只是负责存储消息,并不处理消息(这里指消息的轮训),Looper刚好弥补了这个空缺。我在知道,Handler创建的时候,会默认为我们创建一个Looper对象,那么如何获取当前的Looper呢,这里就使用到了一个TheadLocal的概念,TheadLocal可以轻松的获取当前使用的Looper。

Handler的使用:

Handler )依次存放分属不同线程的行为。

线程在默认的时候是没有Looper与之相关联。在线程中,我们可以通过调用prepare 方法来启动一个消息loop,调用loop方法来通知Looper来处理消息,直至结束。Looper提供了很多的静态方法来与线程、消息队列进行交互。一个线程最多允许创建一个Looper。

以下是SDK文档中介绍的在线程中使用handler的一种方法:

class LooperThread extends Thread {
   public Handler mHandler;
        public void run() {
            Looper.prepare();
            mHandler = new Handler() {
                public void handleMessage(Message msg) {
                    // process incoming messages here
                }
            };
            Looper.loop();
        }

注意这里,官方的例子是和Looper关联了,那么如果我们不关联Looper的话会怎么样呢

 mRunnable = new  Runnable(){
           @Override
           public void run() {
              // TODO Auto-generated method stub
              String s = mHandler.getLooper().getThread().getName();
              Log.e("handler", s);
              mHandler.postDelayed(mRunnable, 1000);
           }};
Thread t  = new Thread(mRunnable,"thread");
        t.start();

运行结果:
ERROR/handler(1630): main,可以发现我们创建了一个名为“thread”的线程,病通过handler发送消息,我们创建的handler自动和UI线程的Looper关联上了。

那么,可不可以在主线程中定义handler,在代码中动态改变handler使之与其他线程的looper相关联呢?是可以的。

mRunnable = new  Runnable(){
              @Override
              public void run() {
                  // TODO Auto-generated method stub
                  Looper.prepare();
                  mHandler = new Handler(Looper.myLooper());
                  String s = mHandler.getLooper().getThread().getName();
                  Log.e("handler", s);
                  mHandler = new Handler(Looper.getMainLooper());
                   s = mHandler.getLooper().getThread().getName();
                  Log.e("handler", s);
              }};
    Thread t  = new Thread(mRunnable,"subthread");
            t.start();

运行结果:

ERROR/handler(4049):subthread

ERROR/handler(4049): main

不过我们Android为我们提供了一个包含Looper的Thead类,HandlerThread  HandlerThread自带了一个Lopper,

 handlerThread=new HandlerThread("handlerThead");
        handlerThread.start();
        handler=new Handler(handlerThread.getLooper());
        handler.post(new Runnable() {
            @Override
            public void run() {
                String s=handler.getLooper().getThread().getName();
                Log.d("test",s);
            }
        });

注:android认为在非线程中操作UI界面是不安全的,因此禁止在其它线程中修改UI界面。解决的方法有两种,一是通过在主线程中定义的handler更新界面,二是直接调用被修改的view的postInvalidate方法刷新单个view。

其实上面的描述是不准确的,实际上在activity第一次执行的时候,是可以在子线程直接更新主线程数据的,条件是不能执行Thread.sleep(),

原因是什么呢?

1.当刚启动Activity即onCreate里面此时onResume方法还没有执行的时候可以,因为在线程中更新UI时会调用ViewParent.invalidateChild()方法检查当前的Thread是否是UIThread,若为UIThread则可以更新(ViewParent是一个接口类,其实现是ViewRootImpl;invalidateChild()方法调用checkThread()方法来检查线程是否为主线程)。ViewRootImp是在onResume方法中初始化的,所以只要在ViewRootImpl创建之前更新UI(在onCreate方法中创建线程并执行,此时还没有初始化ViewRootImp),就可以逃避掉checkThread()的检查进而更新UI。
2.-->刚启动的时候,立即在非UI线程更新->不报错(onResume还没有执行)
--->休眠2s钟以后,更新——————>报错

最后贴上一张图

分析完了Android消息机制的流程,那么我们接下来分别理解一些重要的概念。主要从以下几个方面增强理解,Handler,MessageQueue,Looper和Threadloacal.

android 开发Handler源码剖析的更多相关文章

  1. Android之Handler源码深入分析

    闲着没事,就来看看源码,看看源码的各种原理,会用只是简单的,知道为什么才是最牛逼的. Handler源码分析那,从使用的步骤来边用边分析: 1.创建一个Handler对象:new Handler(ge ...

  2. Python开发【源码剖析】 List对象

    前言 本文探讨的Python版本为2.7.16,可从官网上下载,把压缩包Python-2.7.16.tgz解压到本地即可 需要基本C语言的知识(要看的懂) PyListObject对象 PyListO ...

  3. Android开发之源码:多次点击事件的原理和实现

    多次点击事件 多次点击事件原理:最后一次点击事件与第一次点击事件的时间间隔是否小于某个时间,当小于的时候,就认为这是一个多次点击事件. Android源码实现效果: import android.ap ...

  4. Android开发Settings源码分析之主界面加载(二)

    现在都说互联网寒冬,其实只要自身技术能力够强,咱们就不怕!我这边专门针对Android开发工程师整理了一套[Android进阶学习视频].[全套Android面试秘籍].[Android知识点PDF] ...

  5. Python开发【源码剖析】 Dict对象

    static void ShowDictObject(PyDictObject* dictObject) { PyDictEntry* entry = dictObject->ma_table; ...

  6. 玩转Android之Picasso使用详详详详详详解,从入门到源码剖析!!!!

    Picasso是Squareup公司出的一款图片加载框架,能够解决我们在Android开发中加载图片时遇到的诸多问题,比如OOM,图片错位等,问题主要集中在加载图片列表时,因为单张图片加载谁都会写.如 ...

  7. Android源码剖析之Framework层升级版(窗口、系统启动)

    本文来自http://blog.csdn.net/liuxian13183/ ,引用必须注明出处! 看本篇文章之前,建议先查看: Android源码剖析之Framework层基础版 前面讲了frame ...

  8. Android应用安全开发之源码安全

    Android应用安全开发之源码安全 gh0stbo · 2016/01/21 10:24 0x00 简介 Android apk很容易通过逆向工程进行反编译,从而是其代码完全暴露给攻击者,使apk面 ...

  9. 第一部分:开发前的准备-第八章 Android SDK与源码下载

    第8章 Android SDK与源码下载 如果你是新下载的SDK,请阅读一下步骤了解如何设置SDK.如果你已经下载使用过SDK,那么你应该使用AVD Manager,来更新即可. 下面是构建Andro ...

随机推荐

  1. 【Unity Shader】新书封面 — Low Polygon风格的渲染

    写在前面 最近又开心又担心,因为我的书马上就要上市了,开心当然是因为等了这么久终于可以如愿了,担心是因为不少人对它的期待都很大,我第一次写书,能力也有限,不知道能不能让大家满意,让大家也都喜欢上它.不 ...

  2. APP中一种在Java层实现的简单守护进程方式

    转载请把头部出处链接和尾部二维码一起转载,本文出自逆流的鱼yuiop:http://blog.csdn.net/hejjunlin/article/details/52779986 守护进程是一个黑色 ...

  3. 微信小程序发布

    一.操作步骤 (1)打开[微信开发者工具]->新建一个默认项目->点击[项目]->点击[上传] (2)使用微信小程序公众平台管理员扫描二维码,在手机微信上点击[确认上传] (3)输入 ...

  4. Redis工作系列之一 与 Memcached对比理解

         近期公司项目在使用Redis,这几年Redis很火,Redis也常常被当作Memcached的挑战者被提到桌面上来.关于Redis与Memcached的比较更是比比皆是.然而,Redis真的 ...

  5. Activity平移动画

    Activity平移动画 效果图 添加动画文件 在res下添加anim文件夹,在anim下添加几个动画文件,分别是进入和退出的动画时间和移动距离,属性很简单,一看就懂,不磨叽了. tran_next_ ...

  6. [EXTJS5学习笔记]第二十六节 在eclipse/myeclipse中使用sencha extjs的插件

    本文地址:http://blog.csdn.net/sushengmiyan/article/details/40507383 插件下载: http://download.csdn.net/detai ...

  7. 今天我点亮了CSDN博客专家殊荣

    很久以前,看着csdn博客学习第一篇博客时,我依旧记得,是一个名叫蒋老夫子的博客专家,文章写的非常认真.内心很崇拜.在想,若干年后,在哪个地方?以什么样的一种状态,也得到此殊荣,华为有句口号,叫勇敢做 ...

  8. Android批量打包-如何一秒内打完几百个apk渠道包

    在国内Android常用渠道可能多达几十个,如: 谷歌市场.腾讯应用宝.百度手机助手.91手机商城.360应用平台.豌豆荚.安卓市场.小米.魅族商店.oppo手机.联想乐商.中兴汇天地.华为.安智.应 ...

  9. 控制成本,控制成本知识点,挣值和实际成本、EAC,ETC.TCPI解析表

  10. 使用Swift开发一个MacOS的菜单状态栏App

    猴子原创,欢迎转载.转载请注明: 转载自Cocos2Der-CSDN,谢谢! 原文地址: http://blog.csdn.net/cocos2der/article/details/52054107 ...