zoukankan      html  css  js  c++  java
  • 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会循环获取请求,一个接一个地进行处理。

        

      

  • 相关阅读:
    display:inline-block引发的间隙思考
    HTML中让表单input等文本框为只读不可编辑的方法
    纯CSS实现箭头、气泡让提示功能具有三角形图标(简单实例)
    区分javascript中的toString(),toLocaleString(),valueOf()方法
    Javascript高级程序设计笔记 <第五章> 引用类型
    js数组操作大全
    css中使用if条件在各大浏览器(IE6IE7IE8)中hack方法解决教程
    IE下判断IE版本的语句...[if lte IE 8]……[endif]
    有关opacity或RGBA设置颜色值及元素的透明值
    traceback模块——获取详细的异常信息
  • 原文地址:https://www.cnblogs.com/Jhon-Mr/p/10028028.html
Copyright © 2011-2022 走看看