美文网首页
浅谈IntentService原理分析

浅谈IntentService原理分析

作者: Natchi | 来源:发表于2019-03-07 14:47 被阅读0次

    什么是IntentService?

    一个带有工作线程的,并且具有任务完成会自动停止功能的Service

    一.IntentService的用法
    //继承IntentService,并取个名儿
    class SampleIntentService : IntentService("SampleIntentService") {
    //重写onHandleIntent
       override fun onHandleIntent(intent: Intent?) {
                   //进行耗时操作,这里是工作线程
       }
    //别忘了在mainfest里注册哦
    }
    

    emmmm,IntentService就这么简单,不过这只是用法哦。

    二.IntentService结构组成

    要想了解源码,别单单看别人的技术文章,看是没有用的,最好把源码打开,边看边对着源码了解,那样能理解的快些。
    1.看看继承类

    这里看到IntentService是继承Service
    public abstract class IntentService extends Service
    

    2.看看构造方法

    /**
         * Creates an IntentService.  Invoked by your subclass's constructor.
         *
         * @param name Used to name the worker thread, important only for debugging.
         */
    这里可以看到刚才为嘛给IntentService带个String的参数了,原来给是工作线程取名字呀
        public IntentService(String name) {
            super();
            mName = name;
        }
    

    3.因为是继承Service的,所以我们可以看看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();
       //这里创建工作线程,所以使用intentService为什么不需要创建工作线程
           HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
           thread.start();
       //获取looper,与handler产生联动,实现消息的通信
           mServiceLooper = thread.getLooper();
           mServiceHandler = new ServiceHandler(mServiceLooper);
       }
    

    这里小结下(IntentService里有什么东西)
    1.创建了一个具有looper的工作线程
    2.创建了一个线程通信的Handler
    3.把具有looper的线程跟handler联动

    三.IntentService具体实现

    当一个IntentService开启时,先调用onCreate方法,然后会调用onStartCommand(),然后调用onStart(),储存message,handler发送消息,handleMessage()处理消息,然后onHandleIntent交给子类去实现,等message都处理完了,stopSelf(msg.arg1)停止服务

        //继承Handler类
        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);
            }
        }
        @Override
        public void onStart(@Nullable Intent intent, int startId) {
            Message msg = mServiceHandler.obtainMessage();
            msg.arg1 = startId; //这里要注意,储存这个startId是有用的,后面会讲到
            msg.obj = intent;
            mServiceHandler.sendMessage(msg);
        }
    
        /**
         * You should not override this method for your IntentService. Instead,
         * override {@link #onHandleIntent}, which the system calls when the IntentService
         * receives a start request.
         * @see android.app.Service#onStartCommand
         */
        @Override
        public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
            onStart(intent, startId);
            return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
        }
       @Override
        public void onDestroy() {
            mServiceLooper.quit();
        }
    

    这里有个关键,每次start(),都会把message存储到messagequeue队列中,messagequeue是单线程队列,那么intentService是怎么知道任务全部完成才会去取消任务的呢?
    可以看看ActiveServices源码
    关键代码

    boolean stopServiceTokenLocked(ComponentName className, IBinder token,
                int startId) {
            if (DEBUG_SERVICE) Slog.v(TAG_SERVICE, "stopServiceToken: " + className
                    + " " + token + " startId=" + startId);
            ServiceRecord r = findServiceLocked(className, token, UserHandle.getCallingUserId());
            if (r != null) {
                if (startId >= 0) {
                    // Asked to only stop if done with all work.  Note that
                    // to avoid leaks, we will take this as dropping all
                    // start items up to and including this one.
                    ServiceRecord.StartItem si = r.findDeliveredStart(startId, false);
                    if (si != null) {
                        while (r.deliveredStarts.size() > 0) {
                            ServiceRecord.StartItem cur = r.deliveredStarts.remove(0);
                            cur.removeUriPermissionsLocked();
                            if (cur == si) {
                                break;
                            }
                        }
                    }
    
                    if (r.getLastStartId() != startId) {
                        return false;
                    }
    
                    if (r.deliveredStarts.size() > 0) {
                        Slog.w(TAG, "stopServiceToken startId " + startId
                                + " is last, but have " + r.deliveredStarts.size()
                                + " remaining args");
                    }
                }
    
                synchronized (r.stats.getBatteryStats()) {
                    r.stats.stopRunningLocked();
                }
                r.startRequested = false;
                if (r.tracker != null) {
                    r.tracker.setStarted(false, mAm.mProcessStats.getMemFactorLocked(),
                            SystemClock.uptimeMillis());
                }
                r.callStart = false;
                final long origId = Binder.clearCallingIdentity();
                bringDownServiceIfNeededLocked(r, false, false);
                Binder.restoreCallingIdentity(origId);
                return true;
            }
            return false;
        }
    

    ActiveServices里的stopServiceTokenLocked()里的判断r.getLastStartId()!= startId,来判断当前startId是不是最后一个startId,是就执行r.stats.stopRunningLocked()来终止

    课外知识
    Handler是负责线程间的通信的
    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的线程类,这个looper可以用来跟handler来互动,但一定要用start方法来开启
    

    相关文章

      网友评论

          本文标题:浅谈IntentService原理分析

          本文链接:https://www.haomeiwen.com/subject/ofiqpqtx.html