Android源代码解析之(四)-->HandlerThread

转载请标明出处:一片枫叶的专栏

上一篇文章中我们解说了AsyncTast的基本使用以及实现原理,我们知道AsyncTask内部是通过线程池和Handler实现的。通过对线程池和handler的封装实现了对异步任务操作。很多其它关于AsyncTask相关的内容,可參考我的android源代码解析之(三)–>异步任务AsyncTask

本文我们将解说HandlerThread相关的概念。

HandlerThread是什么东西呢?了解一个类最好的方法就是查看类的定义,所以我们就看一下HandlerThread是怎样定义的吧。

查看类的定义时有这样一段话:

Handy class for starting a new thread that has a looper.
The looper can then be used to create handler classes.
Note that start() must still be called.

意思就是说:这个类的作用是创建一个包括looper的线程。

那么我们在什么时候须要用到它呢?增加在应用程序其中为了实现同一时候完毕多个任务,所以我们会在应用程序其中创建多个线程。为了让多个线程之间能够方便的通信,我们会使用Handler实现线程间的通信。

这个时候我们手动实现的多线程+Handler的简化版就是我们HandlerThrea所要做的事了。

以下我们首先看一下HandlerThread的基本使用方法:

/**
 * 測试HandlerThread的基本使用
 */
HandlerThread mHandlerThread = new HandlerThread("myHandlerThreand");
        mHandlerThread.start();

        // 创建的Handler将会在mHandlerThread线程中运行
        final Handler mHandler = new Handler(mHandlerThread.getLooper()) {
            @Override
            public void handleMessage(Message msg) {
                Log.i("tag", "接收到消息:" + msg.obj.toString());
            }
        };

        title = (TextView) findViewById(R.id.title);
        title.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {

                Message msg = new Message();
                msg.obj = "11111";
                mHandler.sendMessage(msg);

                msg = new Message();
                msg.obj = "2222";
                mHandler.sendMessage(msg);
            }
        });

我们首先定义了一个HandlerThread对象,是直接通过new的方式产生的,查看其构造方法:

public HandlerThread(String name) {
        super(name);
        mPriority = Process.THREAD_PRIORITY_DEFAULT;
    }

能够知道HandlerThread继承于Thread。所以说HandlerThread本质上是一个线程。其构造方法主要是做一些初始化的操作。

然后我们调用了mHandlerThread.start()方法。由上我们知道了HandlerThread类事实上就是一个Thread。一个线程,所以其start方法内部调用的肯定是Thread的run方法,我们查看一下其run方法的详细实现:

@Override
    public void run() {
        mTid = Process.myTid();
        Looper.prepare();
        synchronized (this) {
            mLooper = Looper.myLooper();
            notifyAll();
        }
        Process.setThreadPriority(mPriority);
        onLooperPrepared();
        Looper.loop();
        mTid = -1;
    }

我们发现其内部调用了Looper.prepate()方法和Loop.loop()方法。熟悉android异步消息机制的童鞋应当知道。在android体系中一个线程事实上是相应着一个Looper对象、一个MessageQueue对象。以及N个Handler对象,详细可參考:android源代码解析之(二)–>异步消息机制

所以通过run方法,我们能够知道在我们创建的HandlerThread线程中我们创建了该线程的Looper与MessageQueue。

这里须要注意的是其在调用Looper.loop()方法之前调用了一个空的实现方法:onLooperPrepared(),我们能够实现自己的onLooperPrepared()方法,做一些Looper的初始化操作。

run方法里面当mLooper创建完毕后有个notifyAll(),getLooper()中有个wait(),这是为什么呢?由于的mLooper在一个线程中运行。而我们的handler是在UI线程初始化的,也就是说,我们必须等到mLooper创建完毕,才干正确的返回getLooper();wait(),notify()就是为了解决这两个线程的同步问题

然后我们调用了:

// 创建的Handler将会在mHandlerThread线程中运行
        final Handler mHandler = new Handler(mHandlerThread.getLooper()) {
            @Override
            public void handleMessage(Message msg) {
                Log.i("tag", "接收到消息:" + msg.obj.toString());
            }
        };

该Handler的构造方法中传入了HandlerThread的Looper对象,所以Handler对象就相当于含有了HandlerThread线程中Looper对象的引用。

然后我们调用handler的sendMessage方法发送消息,在Handler的handleMessge方法中就能够接收到消息了。

最后须要注意的是在我们不须要这个looper线程的时候须要手动停止掉;

protected void onDestroy() {
        super.onDestroy();
        mHandlerThread.quit();
    }

好了,以上就是HandlerThread相关的知识了。相对来说HandlerThread还是比較简单的。其本质上就是一个Thread线程,仅仅只是里面包括了Looper和MessageQueue,最后我们在这里总结一下。

总结:

  • HandlerThread本质上是一个Thread对象。仅仅只是其内部帮我们创建了该线程的Looper和MessageQueue;
  • 通过HandlerThread我们不但能够实现UI线程与子线程的通信相同也能够实现子线程与子线程之间的通信。
  • HandlerThread在不须要使用的时候须要手动的回收掉;

另外对android源代码解析方法感兴趣的可參考我的:

android源代码解析之(一)–>android项目构建过程

android源代码解析之(二)–>异步消息机制

android源代码解析之(三)–>异步任务AsyncTask



本文以同步至github中:https://github.com/yipianfengye/androidSource,欢迎star和follow


时间: 2024-08-09 02:19:14

Android源代码解析之(四)-->HandlerThread的相关文章

Android源代码解析之(六)-->Log日志

转载请标明出处:一片枫叶的专栏 首先说点题外话,对于想学android framework源代码的同学,事实上能够在github中fork一份,详细地址:platform_frameworks_base 这里面基本都是android framework层的源代码了.并且近期发现了一个比較不错的github插件:OctoTree,它 是一个浏览器插件,它能够让你在Github 看代码时,左边栏会出现一个树状结构.就像我们在IDE 一样.当我们看一个项目的结构,或者想看详细的某个文件,这样就会非常方

Android源代码解析之(十三)-->apk安装流程

转载请标明出处:一片枫叶的专栏 上一篇文章中给大家分析了一下android系统启动之后调用PackageManagerService服务并解析系统特定文件夹.解析apk文件并安装的过程,这个安装过程实际上是没有图形界面的,底层调用的是我们平时比較熟悉的adb命令,那么我们平时安装apk文件的时候大部分是都过图形界面安装的,那么这样的方式安装apk详细的流程是如何的呢? 本文我们就来详细看一下apk的详细安装过程,通过本文的学习希望帮助大家大概的了解到Android系统安装Apk文件的基本流程.好

Android源代码解析之(七)-->LruCache缓存类

转载请标明出处:一片枫叶的专栏 android开发过程中常常会用到缓存.如今主流的app中图片等资源的缓存策略通常是分两级.一个是内存级别的缓存,一个是磁盘级别的缓存. 作为android系统的维护者google也开源了其缓存方案,LruCache和DiskLruCache.从android3.1開始LruCache已经作为android源代码的一部分维护在android系统中.为了兼容曾经的版本号android的support-v4包也提供了LruCache的维护,假设App须要兼容到andr

Android源代码解析之(三)-->异步任务AsyncTask

转载请标明出处:一片枫叶的专栏 上一篇文章中我们解说了android中的异步消息机制. 主要解说了Handler对象的使用方式.消息的发送流程等.android的异步消息机制是android中多任务处理的基础,Handler是整个android应用层体系异步消息传递的基础组件,通过对Handler源代码的解析的解析相信大家对android中的异步消息机制有了一个大概的了解.很多其它关于android中的异步消息机制的知识可參考我的:android源代码解析之(二)–>异步消息机制 android

Android volley 解析(四)之缓存篇

这是 volley 的第四篇 blog 了,写完这篇,volley 的大部分用法也都算写了一遍,所以暂时不会写 volley 的文章了,如果想看我前面写的文章,可以点这里 Android volley 解析(三)之文件上传篇 为什么要用缓存 我们知道,当客户端在请求网络数据的时候,是需要消耗流量的,特别是对于移动端用户来说,对于流量的控制要求很高.所以在做网络请求的时候,如果对数据更新要求不是特别高,往往都会用到缓存机制,一方面能减少对服务端的请求,控制流量:另一方面,当客户端在没有网络的情况下

Android 源代码解析 之 setContentView

大家在平时的开发中.对于setContentView肯定不陌生,那么对其内部的实现会不会比較好奇呢~~~有幸最终能看到一些PhoneWindow神马的源代码,今天就带大家来跑一回源代码~~ 1.Activity  setContentView 首先不用说,进入Activity的setContentView public void setContentView(int layoutResID) { getWindow().setContentView(layoutResID); initActio

Android View体系(八)从源代码解析View的layout和draw流程

相关文章 Android View体系(一)视图坐标系 Android View体系(二)实现View滑动的六种方法 Android View体系(三)属性动画 Android View体系(四)从源代码解析Scroller Android View体系(五)从源代码解析View的事件分发机制 Android View体系(六)从源代码解析Activity的构成 Android View体系(七)从源代码解析View的measure流程 前言 上一篇文章我们讲了View的measure的流程.接

《Android源代码设计模式解析与实战》读书笔记(十)

第十章.解释器模式 解释器模式是一种用的比較少的行为型模式.其提供了一种解释语言的语法或表达式的方式. 可是它的使用场景确实非常广泛,仅仅是由于我们自己非常少回去构造一个语言的文法,所以使用较少. 1.定义 给定一个语言,定义它的文法的一种表示,并定义一个解释器,该解释器使用该表示来解释语言中的句子. (当中语言就是我们须要解释的对象,文法就是这个语言的规律,解释器就是翻译机.通过文法来翻译语言.) 2.使用场景 1.假设某个简单的语言须要解释运行并且能够将该语言中的语句表示为一个抽象的语法树时

Android SVG动画PathView源代码解析与使用教程(API 14)

使用的是一个第三方库android-pathview主要是一个自己定义View--PathView.跟全部自己定义View一样,重写了三个构造方法. 而且终于调用三个參数的构造方法,在里面获取自己定义属性. /** * Default constructor. * * @param context The Context of the application. */ public PathView(Context context) { this(context, null); } /** * D