Android之Handler和Loooper源码分析(1)

简介: Android之Handler和Loooper源码分析

1、handler在主线程和子线程互相通信(子线程和子线程的通信)简单使用

     我们使用handler,可以实现主线程和子线程之间的相互通信,然后子线程和子线程之间的通信,如果不清楚,基本用法请先参考我的这篇博客


Android之用Handler实现主线程和子线程互相通信以及子线程和子线程之间的通信  http://blog.csdn.net/u011068702/article/details/75577005



2、handler在主线程为什么不需要调用Looper.prepare()

我们看下Looper.java这个类,它在安卓android.os包下,我们看这个类的一开始的注释

  * <p>This is a typical example of the implementation of a Looper thread,
  * using the separation of {@link #prepare} and {@link #loop} to create an
  * initial Handler to communicate with the Looper.
  *
  * <pre>
  *  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();
  *      }
  *  }</pre>

很明显,在一个线程里面需要使用Handler之前需要Looper.prepare(),但是我们平时在主线程更新UI的时候,为什么没有看到这行代码呢?



我们看下ActivityThread.java这个类,它在安卓包名android.app目录下,我们知道ActivityThread.java这个类是安卓程序的入口,我们看下main函数的代码

    public static void main(String[] args) {
        SamplingProfilerIntegration.start();
        // CloseGuard defaults to true and can be quite spammy.  We
        // disable it here, but selectively enable it later (via
        // StrictMode) on debug builds, but using DropBox, not logs.
        CloseGuard.setEnabled(false);
        Environment.initForCurrentUser();
        // Set the reporter for event logging in libcore
        EventLogger.setReporter(new EventLoggingReporter());
        Security.addProvider(new AndroidKeyStoreProvider());
        // Make sure TrustedCertificateStore looks in the right place for CA certificates
        final File configDir = Environment.getUserConfigDirectory(UserHandle.myUserId());
        TrustedCertificateStore.setDefaultUserDirectory(configDir);
        Process.setArgV0("<pre-initialized>");
        Looper.prepareMainLooper();
        ActivityThread thread = new ActivityThread();
        thread.attach(false);
        if (sMainThreadHandler == null) {
            sMainThreadHandler = thread.getHandler();
        }
        if (false) {
            Looper.myLooper().setMessageLogging(new
                    LogPrinter(Log.DEBUG, "ActivityThread"));
        }
        Looper.loop();
        throw new RuntimeException("Main thread loop unexpectedly exited");
    }


我们可以看到有Looper.prepareMainLooper()函数,我们点击进去

public static void prepareMainLooper() {
        prepare(false);
        synchronized (Looper.class) {
            if (sMainLooper != null) {
                throw new IllegalStateException("The main Looper has already been prepared.");
            }
            sMainLooper = myLooper();
        }
    }


然后看到了prepare(false)函数,我们再点击这个函数


private static void prepare(boolean quitAllowed) {
        if (sThreadLocal.get() != null) {
            throw new RuntimeException("Only one Looper may be created per thread");
        }
        sThreadLocal.set(new Looper(quitAllowed));
    }

我们可以看到这里就调用prepare函数,所以主线程不需要调用Looper.prepare()函数,然后我们也可以看到这里有行这个代码




       if (sThreadLocal.get() != null) {

           throw new RuntimeException("Only one Looper may be created per thread");

       }


在Looper.java类中,我们的Looper保存在ThreadLocal里面




static final ThreadLocal<Looper> sThreadLocal = new ThreadLocal<Looper>();

用ThreadLocal修饰的变量,可以理解为只有当前线程可以改变这个参数,其它线程不可以改变这个参数,如果你对ThreadLocal不清楚,单独可以先看下我这篇博客的简单使用



java之ThreadLocal简单使用总结    http://blog.csdn.net/u011068702/article/details/75770226
        if (sThreadLocal.get() != null) {
            throw new RuntimeException("Only one Looper may be created per thread");
        }

上面的代码写得很清楚了,如果当前的sThreadLocal对象里面有个Looper对象,那么就会抛出异常,而且英文也提示了,所以,一个线程为什么只能有一个Looper对象的原因,所以如果在程序里面,每个线程调用2次Looper.prepare()就会报错,我们再看这行代码




       sThreadLocal.set(new Looper(quitAllowed));


点击Looper的构造函数



private Looper(boolean quitAllowed) {
        mQueue = new MessageQueue(quitAllowed);
        mThread = Thread.currentThread();
    }

里面构建了一个MessageQueue对象,上面我们分析一个线程只有一个Looper对象,那么Looper对象只构建一个,也就意味着MessageQueue对象也只构建一次,所以一个线程也只有一个MessageQueue对象的原因。



在main函数里面,也调用了Looper.loop()函数,后面分析这个方法



 


相关文章
|
10月前
|
消息中间件 网络协议 Java
Android 开发中实现数据传递:广播和Handler
Android 开发中实现数据传递:广播和Handler
110 1
|
10月前
|
安全 Android开发 开发者
【Android开发小技巧】扔掉这坑人的 Handler
【Android开发小技巧】扔掉这坑人的 Handler
99 0
|
5月前
|
消息中间件 存储 Java
Android消息处理机制(Handler+Looper+Message+MessageQueue)
Android消息处理机制(Handler+Looper+Message+MessageQueue)
68 2
|
5月前
|
消息中间件 存储 Java
Android面试高频知识点(2) 详解Android消息处理机制(Handler)
Android面试高频知识点(2) 详解Android消息处理机制(Handler)
|
5月前
|
消息中间件 存储 Java
Android面试高频知识点(2) 详解Android消息处理机制(Handler)
Android面试高频知识点(2) 详解Android消息处理机制(Handler)
83 1
|
5月前
|
消息中间件 存储 Java
Android消息处理机制(Handler+Looper+Message+MessageQueue)
Android消息处理机制(Handler+Looper+Message+MessageQueue)
140 2
|
7月前
|
消息中间件 存储 Java
Android面试高频知识点(2) 详解Android消息处理机制(Handler)
Android 消息处理机制估计都被写烂了,但是依然还是要写一下,因为Android应用程序是通过消息来驱动的,Android某种意义上也可以说成是一个以消息驱动的系统,UI、事件、生命周期都和消息处理机制息息相关,并且消息处理机制在整个Android知识体系中也是尤其重要,在太多的源码分析的文章讲得比较繁琐,很多人对整个消息处理机制依然是懵懵懂懂,这篇文章通过一些问答的模式结合Android主线程(UI线程)的工作原理来讲解,源码注释很全,还有结合流程图,如果你对Android 消息处理机制还不是很理解,我相信只要你静下心来耐心的看,肯定会有不少的收获的。
274 3
Android面试高频知识点(2) 详解Android消息处理机制(Handler)
|
8月前
|
消息中间件 调度 Android开发
Android经典面试题之View的post方法和Handler的post方法有什么区别?
本文对比了Android开发中`View.post`与`Handler.post`的使用。`View.post`将任务加入视图关联的消息队列,在视图布局后执行,适合视图操作。`Handler.post`更通用,可调度至特定Handler的线程,不仅限于视图任务。选择方法取决于具体需求和上下文。
90 0
|
9月前
|
Android开发
38. 【Android教程】Handler 消息传递机制
38. 【Android教程】Handler 消息传递机制
93 2
|
Android开发
Android PackageManagerService源码分析和APK安装原理详解
Android PackageManagerService源码分析和APK安装原理详解
606 1

热门文章

最新文章

  • 1
    Android历史版本与APK文件结构
  • 2
    【01】噩梦终结flutter配安卓android鸿蒙harmonyOS 以及next调试环境配鸿蒙和ios真机调试环境-flutter项目安卓环境配置-gradle-agp-ndkVersion模拟器运行真机测试环境-本地环境搭建-如何快速搭建android本地运行环境-优雅草卓伊凡-很多人在这步就被难倒了
  • 3
    【03】仿站技术之python技术,看完学会再也不用去购买收费工具了-修改整体页面做好安卓下载发给客户-并且开始提交网站公安备案-作为APP下载落地页文娱产品一定要备案-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-优雅草卓伊凡
  • 4
    【01】仿站技术之python技术,看完学会再也不用去购买收费工具了-用python扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-客户的麻将软件需要下载落地页并且要做搜索引擎推广-本文用python语言快速开发爬取落地页下载-优雅草卓伊凡
  • 5
    【03】微信支付商户申请下户到配置完整流程-微信开放平台创建APP应用-填写上传基础资料-生成安卓证书-获取Apk签名-申请+配置完整流程-优雅草卓伊凡
  • 6
    【02】仿站技术之python技术,看完学会再也不用去购买收费工具了-本次找了小影-感觉页面很好看-本次是爬取vue需要用到Puppeteer库用node.js扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-优雅草卓伊凡
  • 7
    Cellebrite UFED 4PC 7.71 (Windows) - Android 和 iOS 移动设备取证软件
  • 8
    escrcpy:【技术党必看】Android开发,Escrcpy 让你无线投屏新体验!图形界面掌控 Android,30-120fps 超流畅!🔥
  • 9
    Android实战经验之Kotlin中快速实现MVI架构
  • 10
    即时通讯安全篇(一):正确地理解和使用Android端加密算法