Android源码之路(一、IntentService)

作者: CodeInfo | 来源:发表于2018-07-22 17:29 被阅读4次

    前言

    源码分析篇,分析过程也参考过各位大神的成果。知识在于分享,学会了就是自己的,有参考过的,也会尽量给出链接(看了很多,可能无法一一给出);希望共同进步,站在巨人肩膀上看世界!
    参考:http://blog.csdn.net/smbroe/article/details/45009721

    以下用法和源码分析基于android-27(即版本android 8.1.0)

    要点总结

    1.生命周期onCreate --> onStartCommand --> onStart --> onHandleIntent --> onDestroy
        其中onCreate、onStartCommand、onStart、onDestroy运行在ui线程,onHandleIntent运行在子线程;
    
    2.如果每次onHandleIntent执行的时间足够长的话,连续循环启动IntentService的
        onCreate只会执行一次,而onStartCommand、onStart则启动几次就执行几次,onHandleIntent也是启动几次就执行几次,onDestroy只执行一次;
     
        对应onHandleIntent来说是串行的,对同一进程内同一IntentService来说必须按序排队依次执行;
        
        即如果IntentService未执行完任务时,不会再次启动新的IntentService,而是会使用原IntentService排队执行任务,全部任务执行完毕后,才退出IntentServie;
    
    3.如果启动IntentService时,前边的任务已经执行结束并退出后,则会再次创建onCreate并执行
    
    4.需要提供无参的构造函数,然后调用父类的有参构造;Service的实例化是系统来完成的,而且系统是用参数为空的构造函数来实例化Service的
    
    5.假设在onHandleIntent中创建handler并执行操作:
        @Override
        protected void onHandleIntent(@Nullable Intent intent) {
            Log.d(TAG,"onHandleIntent"+" ,"+Thread.currentThread());
             Handler temphandler=new Handler(){
                 @Override
                 public void handleMessage(Message msg) {
                     Log.d(TAG,"handleMessage"+" ,"+Thread.currentThread());
                 }
             };
             temphandler.sendEmptyMessageDelayed(1,5000);
        }
        这样handleMessage是不会执行的,因为此时temphandler获取的是intentService中HandlerThread的looper,而在onHandleIntent执行完后,会调用onDestroy退出整个消息队列,所以这边的handleMessage就执行不到了;
        
        如果temphandler是在外部初始化的就可以,默认会拿的mainlooper;
    

    优缺点

    优点:
            1.与service都运行于ui线程不同,intentService在子线程中处理耗时任务,避免堵塞造成anr;
            2.自己维护消息队列,实现排队执行,避免多线程资源同步问题;
            3.无需手动停止intentservice,任务都执行完毕后自动销毁;
            4.存在已启动的正在使用的intentServie的话,再次启动不会重复创建,而是共用一个节省不必要资源开销
            
    缺点:  1.处理完成之后要通知ui的话,相对麻烦,可能需要使用ui线程的handler或者广播。
    

    使用方法

    //创建实现IntentService的子类并在AndroidMainfest.xml中声明
    <service android:name=".MyIntentService"></service>
    
    public class MyIntentService extends IntentService{
        String TAG="MyIntentService";
        
        public MyIntentService() {   //需要提供默认的无参构造函数,然后调用父类的有参构造
            this("MyIntentService");
        }
        public MyIntentService(String name) {
            super(name);
        }
    
        @Override
        public void setIntentRedelivery(boolean enabled) {
            super.setIntentRedelivery(enabled);
            Log.d(TAG,"setIntentRedelivery:"+enabled+" ,"+Thread.currentThread());
        }
    
        @Override
        public void onCreate() {
            super.onCreate();
            Log.d(TAG,"onCreate"+" ,"+Thread.currentThread());
        }
    
        @Override
        public void onStart(@Nullable Intent intent, int startId) {
            super.onStart(intent, startId);
            Log.d(TAG,"onStart"+" ,"+Thread.currentThread());
        }
        
        //这边的intent可以获取startService中传递进来的参数
        @Override
        public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
            Log.d(TAG,"onStartCommand:"+startId+" ,"+Thread.currentThread());
            return super.onStartCommand(intent, flags, startId);
    
        }
    
        @Override
        public void onDestroy() {
            super.onDestroy();
            Log.d(TAG,"onDestroy"+" ,"+Thread.currentThread());
        }
    
        @Nullable
        @Override
        public IBinder onBind(Intent intent) {
            Log.d(TAG,"onBind"+" ,"+Thread.currentThread());
            return super.onBind(intent);
        }
    
        //这边的intent可以获取startService中传递进来的参数
        @Override
        protected void onHandleIntent(@Nullable Intent intent) {
            Log.d(TAG,"onHandleIntent"+" ,"+Thread.currentThread());
        }
    }
    
        
        
        //启动intentService
        Intent intent = new Intent(SecondActivity.this,MyIntentService.class);
        intent.putExtra("parmas1","abcd");//..按需要携带参数
        intent.putExtra("parmas2",true);
        SecondActivity.this.startService(intent);
    

    源码分析

    onCreate函数

    private volatile Looper mServiceLooper;
        private volatile ServiceHandler mServiceHandler;
        @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);
        }
    
    在OnCreate中创建了一个HandlerThread,并获取其中的looper创建ServiceHandler(继承自Handler),使得ServiceHandler可以在子线程中处理消息
    

    onStartCommand函数

    /**
         * 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;
        }
    
    对于onStartCommand只是简单的调用了onStart方法
    

    onStart函数

    @Override
        public void onStart(@Nullable Intent intent, int startId) {
            Message msg = mServiceHandler.obtainMessage();
            msg.arg1 = startId;
            msg.obj = intent;
            mServiceHandler.sendMessage(msg);
        }
    
    在onStart方法中,所做的处理便是将startService传递过来的Intent和启动startId包装在Message中传递给ServiceHandler进行处理
    

    回调onHandleIntent处理消息

    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);
            }
        }
    
    而在ServiceHandler中,便是回调执行用户重写的onHandleIntent方法,
    执行完毕之后,注意调用的stopSelf(startId),Handler中我们处理完每一个命令都会调用stopSelf(int)方法来停止服务:该方法需要来自onStartCommand方法中的启动ID,只有传入的startId是onStartCommand方法中接收到的最新启动ID时才会停止服务,就是说,我们的IntentService直到命令队列中的所有命令被执行完后才会停止服务。
    
    
    //会停止service并回调onDestroy
    public final void stopSelf() {
        stopSelf(-1);
    }
    
    //会判断传入的startId与当前startService所传入的startId是否一致,一致才停止Service并回调onDestroy,否则不停止,由此实现连续多次启动IntentService时,每次回调执行完onHandleIntent后,不会立即退出IntentService,而是接着执行Handler队列中的消息
    public final void stopSelf(int startId) {
        if (mActivityManager == null) {
            return;
        }
        try {
            mActivityManager.stopServiceToken(
                    new ComponentName(this, mClassName), mToken, startId);
        } catch (RemoteException ex) {
        }
    }
    

    onDestroy函数

    @Override
        public void onDestroy() {
            mServiceLooper.quit();
        }
    
    退出消息队列
    
    qrcode_for_gh_1bbc19ef669d_258.jpg

    相关文章

      网友评论

        本文标题:Android源码之路(一、IntentService)

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