Android源码之路(一、IntentService)

前言

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

参考: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();
    }
复制代码
退出消息队列

猜你喜欢

转载自blog.csdn.net/a8082649/article/details/81166125