Android IntentService源码理解 及 HandlerThread构建消息循环机制分析

  前言:前面写了Handler的源码理解,关于Handler在我们Android开发中是到处能见到的异步通信方式。那么,在Android原生里,有那些也有到了Handler机制的呢?有很多,比如我们今天所要理解分析的IntentService就使用到了Handler。接下来,我们来深入了解一下。

  HandlerThread:

  IntentService使用到了Handler+HandlerThread构建的带有消息循环的异步任务处理机制,我们先简单看一下HandlerThread是如何工作的吧。

  HandlerThread的使用步骤:

        // 创建HandlerThread实例
        HandlerThread handlerThread = new HandlerThread("handlerThread");
        // 启动HandlerThread线程
        handlerThread.start();
        // 构建消息循环处理机制
        Handler handler = new Handler(handlerThread.getLooper(), new Handler.Callback() {

            @Override
            public boolean handleMessage(Message msg) {
                return false;
            }
        });

  以上三步的顺序不能乱,必须严格按照步骤来。第三步是将HandlerThread对象中的looper对象作为Handler第一个参数,我们由前面的Handler解析可知道,我们指定了Looper对象,那我们的handler的线程looper对象就不用新建,而是使用当前传入的线程的looper对象。

  第一步,创建HandlerThread对象,HandlerThread我们能看到,它继承自Thread,它有两个构造函数

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

  两个构造方法的都需要传一个任意字符串参数,参数的主要作用就是指定该线程的名称;第二个构造方法多传一个优先级参数,不传则默认第一个构造方法中的Process.THREAD_PRIORITY_DEFAULT,根据需求自行决定即可;

  第二步,启动HandlerThread线程,为什么我们必须要先启动HandlerThread,我们来看看run()就明白了

    @Override
    public void run() {     // 获得当前线程的id
        mTid = Process.myTid();     // 准备循环条件
        Looper.prepare();     // 持有锁机制来获得当前线程的Looper对象
        synchronized (this) {
            mLooper = Looper.myLooper();       // 发出通知,当前线程已经创建mLooper对象成功,这里主要是通知getLooper方法中的wait
            notifyAll();
        }     // 设置当前线程的优先级
        Process.setThreadPriority(mPriority);     // 该方法实现体是空的,子类可以实现该方法,作用就是在线程循环之前做一些准备工作,当然子类也可以不实现。  
        onLooperPrepared();     // 启动loop
        Looper.loop();
        mTid = -1;
    }

  代码注释写的非常清楚了,在run()方法中主要是调用了Looper.prepare()和Loop.loop()构建了一个循环线程;我们可以注意一下的是,在loop()循前调用了onLooperPreapared()方法,这个方法可自行实现,做一些线程循环之前的准备工作,这就有了很好的拓展性了;notifyAll()主要是通知getLooper()中的wait,我们看一下getLooper()方法;

    public Looper getLooper() {
        if (!isAlive()) {
            return null;
        }

        // If the thread has been started, wait until the looper has been created.
        // 如果线程已启动,looper对象为空,则继续等待,前面的唤醒就可以唤醒当前的等待
        synchronized (this) {
            while (isAlive() && mLooper == null) {
                try {
                    wait();
                } catch (InterruptedException e) {
                }
            }
        }
        return mLooper;
    }

  第三步,构建消息循环机制,该步骤这里就不详细说了,前面《Android异步消息处理机制掌握,从源码了解常使用的Handler》看过后就能理解了。

  OK,我们讲了这么多HandlerThread的分析理解,那么IntentService的理解就比较容易了,我们现在来看看IntentService吧;

    public IntentService(String name) {
        super();
        mName = name;
    }

  IntentService是继承自Service的,是启动一个服务进行异步任务处理的,该服务会在执行完任务后自行终止;IntentService的构造函数很简单,传入一个字符串参数,指定线程名称;

  我们都知道Service服务生命周期是从onCreate方法开始的,首先来看看onCreate方法做了什么

    @Override
    public void onCreate() {
        // TODO: It would be nice to have an option to hold a partial wakelock
        // during processing, and to have a static startService(Context, Intent)
        // method that would launch the service & hand off a wakelock.

        super.onCreate();
        HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
        thread.start();

        mServiceLooper = thread.getLooper();
        mServiceHandler = new ServiceHandler(mServiceLooper);
    }

  很开心,我们刚刚分析的HandlerThread在这里出现了。onCreate方法创建了一个循环的工作线程HandlerThread,然后将HandlerThread当前线程的looper对象传给Handler作为参数创建一个消息执行者,通过Handler+HandlerThread构建了一个带有消息循环机制的异步任务处理机制;ServiveHandler是IntentService的一个内部类,继承Handler;

  Service服务第二步生命周期执行onStartCommand方法;

    @Override
    public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
        onStart(intent, startId);
        return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
    }

  我们看到该方法仅仅调用了onStart方法,在IntentService的子类中无需重写该方法,系统会在IntentService接受一个请求开始调用该方法;

    @Override
    public void onStart(@Nullable Intent intent, int startId) {
        Message msg = mServiceHandler.obtainMessage();
        msg.arg1 = startId;
        msg.obj = intent;
        mServiceHandler.sendMessage(msg);
    }

  该方法就是通过ServiceHandler获取一个Message对象,将异步消息请求的intent封装进Message中,并发送给ServiceHandler消息执行者中去处理;

    private final class ServiceHandler extends Handler {
        public ServiceHandler(Looper looper) {
            super(looper);
        }

        @Override
        public void handleMessage(Message msg) {
            onHandleIntent((Intent)msg.obj);
            stopSelf(msg.arg1);
        }
    }

  实现很简单,继承Handler,在重写消息处理方法中调用IntentService的onHandleIntent方法,onHandleIntent方法也是我们使用IntentService需要重写的方法,在这个我们进行我们的异步任务操作。为什么可以在这里进行异步任务操作,当异步任务结束后,调用stopSelf方法自动结束该IntentService服务。前面HandlerThread理解后我们可以知道这里的handleMessage是在工作线程中执行的;那这样我们就达到了异步任务处理的目的了。

  

    /**
     * This method is invoked on the worker thread with a request to process.
     * Only one Intent is processed at a time, but the processing happens on a
     * worker thread that runs independently from other application logic.
     * So, if this code takes a long time, it will hold up other requests to
     * the same IntentService, but it will not hold up anything else.
     * When all requests have been handled, the IntentService stops itself,
     * so you should not call {@link #stopSelf}.
     *
     * @param intent The value passed to {@link
     *               android.content.Context#startService(Intent)}.
     *               This may be null if the service is being restarted after
     *               its process has gone away; see
     *               {@link android.app.Service#onStartCommand}
     *               for details.
     */
    @WorkerThread
    protected abstract void onHandleIntent(@Nullable Intent intent);

  onHandleIntent方法是我们使用IntentService的时候在子类需要重写的方法。通过注释我们可以知道,每一次只能处理一个intent意图请求,当有多个请求时(客户端多次调用startCommand方法),其他intent暂时会被阻塞挂起,直到前面的intent请求处理完成才会继续处理下一个intent请求。处理完成请求后,调用stopSelf方法停止当前服务,然后会继而调用Service的onDestroy生命周期方法,从而达到处理完成任务后,服务销毁;

    public final void stopSelf(int startId) {
        if (mActivityManager == null) {
            return;
        }
        try {
            mActivityManager.stopServiceToken(
                    new ComponentName(this, mClassName), mToken, startId);
        } catch (RemoteException ex) {
        }
    }
    @Override
    public void onDestroy() {
        mServiceLooper.quit();
    }

  总结:IntentService是一种异步任务处理的方式,继承自Service,使用IntentService需在子类重写onHandleIntent方法,进行异步任务。只要当前服务没有销毁,客户端可以发起多个Intent请求,looper会循环获取请求,一个接一个地进行处理。

    

  

原文地址:https://www.cnblogs.com/Jhon-Mr/p/10028028.html

时间: 2024-10-13 13:33:21

Android IntentService源码理解 及 HandlerThread构建消息循环机制分析的相关文章

Android IntentService 源码分析

IntentService简介: IntentService是一个通过Context.startService(Intent)启动可以处理异步请求的Service,使用时你只需要继承IntentService和重写其中的onHandleIntent(Intent)方法接收一个Intent对象,该服务会在异步任务完成时自动停止服务. 所有的请求的处理都在IntentService内部工作线程中完成,它们会顺序执行任务(但不会阻塞主线程的执行),某一时刻只能执行一个异步请求. IntnetServi

Android消息传递源码理解。Handler,Looper,MessageQueue,Message

Android中消息传递模块差不多看了好几次,虽然每次看的方式都差不多但是还是发觉的到每次看了之后,理解的更清晰一点. 关于这个模块的文章数不胜数,但是最重要的还是自己动手理解一遍更好. 会牵扯到的几个类: Handler.java  , Looper.java , MessageQueue.java , Message.java 源代码路径: xxx/frameworks/base/core/java/android/os  看的过程中你会发现高版本和低版本系统代码有些地方比较大的差距.从中我

Android设计模式源码解析之观察者模式

Android设计模式源码解析之观察者模式 本文为 Android 设计模式源码解析 中 观察者模式 分析 Android系统版本: 2.3 分析者:Mr.Simple,分析状态:未完成,校对者:Mr.Simple,校对状态:未开始 1. 模式介绍 模式的定义 定义对象间一种一对多的依赖关系,使得每当一个对象改变状态,则所有依赖于它的对象都会得到通知并被自动更新. 模式的使用场景 关联行为场景.需要注意的是,关联行为是可拆分的,而不是"组合"关系: 事件多级触发场景: 跨系统的消息交换

Android进阶:二、从源码角度看透 HandlerThread 和 IntentService

上篇文章我们讲日志的存储策略的时候用到了HandlerThread,它适合处理"多而小的任务"的耗时任务的时候,避免产生太多线程影响性能,那这个HandlerThread的原理到底是怎样的呢?我们现在从源码角度解读 HandlerThread:继承自Thread,是一个可以使用Handler的Thread.因为在run方法内维护了一个Looper,可以通过Handler发送消息的方式,来通知HandlerThread执行一个具体的任务. public void run() { mTid

Android Launcher源码研究(二) 加载app流程1

今天主要分析Android Launcher源码中的一些重要类之间的关系,基本的加载流程.先来看一个类图 Launcher.java 是主Activity 在onCreate方法里面初始化了LauncherMode实例. LauncherApplication app = ((LauncherApplication)getApplication()); mModel = app.setLauncher(this); 直接进入LauncherApplication.java的方法 Launcher

IntentService源码详解

IntentService可以做什么: 如果你有一个任务,分成n个子任务,需要它们按照顺序完成.如果需要放到一个服务中完成,那么IntentService就会使最好的选择. IntentService是什么: IntentService是一个Service(看起来像废话,但是我第一眼看到这个名字,首先注意的是Intent啊.),所以如果自定义一个IntentService的话,一定要在AndroidManifest.xml里面声明. 从上面的"可以做什么"我们大概可以猜测一下Inten

Android Launcher源码结构

Launcher 是 Android手机开启后第一个运行的 应用程序,也叫Home,或者叫做手机桌面. 本文介绍的是4.1源码的launcher2 app. Android41\packages\apps\Launcher2 首先找到主Activity,打开AndroidManifest.xml  入口是  com.android.launcher2.Launcher 这个类 Launcher 主界面包含 wallpaper墙纸,work_screen屏幕, 最底部的hotseat, 以及all

2016年最牛逼的分类Android项目源码免费一次性打包下载!

之前发过一个帖子,但是那个帖子有点问题我就重新发一个吧,下面的源码是我从今年开始不断整理源码区和其他网站上的安卓例子源码,目前总共有810套左右,根据实现的功能被我分成了100多个类,总共接近2.5G,还在不断更新.初学者可以快速方便的找到自己想要的例子,大神也可以看一下别人的方法实现.虽然的例子都是我一个人辛辛苦苦花了很多时间和精力整理的,但是既然这些例子是来自于社区那就让他们免费回归社区吧,(是的!特么的不要一分钱!最看不起那些挂羊头卖狗的)你可以在本帖里面按Ctrl+F查找你需要的关键字,

[Android]Fragment源码分析(一) 构造

Fragment是Android3.0之后提供的api,被大家广泛所熟知的主要原因还是因为随即附带的ViewPager控件.虽然我并不喜欢用它,但是它确实是一个相对不错的控件.还是我的一贯作风,我将从源码上向大家展示什么是Fragment.我们先写一个简单的代码对Fragment有个直观的认识:(为了保证我们方便调试,我们可以直接使用V4提供的源码包) FragmentTransaction t = getSupportFragmentManager().beginTransaction();