IntentService 深度解析(实例 + 源码)

上一篇:

Service 深度解析

上文说过

  • Service默认工作在当前进程的主线程中,如需执行耗时操作,需要手动开启线程;
  • 且一旦开启服务,就会一直运行,直到stopService()或者stopSelf();

IntentService内置线程,且线程执行结束后,会自动终止服务

IntentService的使用

模拟下载一个视频文件的功能:

1、AndroidManifest中注册

<service android:name=".update.UpdateService" />

2、自定义Service继承自IntentService

以下两个方法必须实现,其余是为了探讨IntentService的生命周期,可以自行去掉

  • 实现空参构造方法UpdateService(),super(“xx”) //xx是定义的线程名
  • onHandleIntent(),onHandleIntent是在子线程中运行的,可以直接执行耗时操作。
public class UpdateService extends IntentService {

//必须实现,指定线程名
    public UpdateService() {
        super("customThread");
        Log.e("zhen", "UpdateService: customThread"  );
    }

    @Override
    public void onCreate() {
        super.onCreate();
        Log.e("zhen", "UpdateService: onCreate ");
    }

    @Override
    public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
        Log.e("zhen", "UpdateService: onStartCommand ");
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.e("zhen", "UpdateService: onDestroy ");
    }

    @Override
    public void onStart(@Nullable Intent intent, int startId) {
        super.onStart(intent, startId);
        Log.e("zhen", "UpdateService: onStart ");
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        Log.e("zhen", "UpdateService: onBind ");
        return super.onBind(intent);
    }

//必须实现,默认在子线程中操作
    @Override
    protected void onHandleIntent(@Nullable Intent intent) {
        Log.e("zhen", "UpdateService: onHandleIntent thread: " + Thread.currentThread().toString());
        Log.e("zhen", "开始下载");
        int i = 0;
        try {
            do {
                Thread.sleep(2000);
                i += 20;
                Log.e("zhen", "下载进度: " + i + "% ...");
            } while (i < 100);
            Log.e("zhen", "下载完成!");
        } catch (InterruptedException e) {
            e.printStackTrace();
            Log.e("zhen", "下载失败!");
        }
    }
}

3、启动service

Intent intent = new Intent(this, UpdateService.class)
startService(intent)

IntentService 生命周期

日志打印:

1、点击一次startService

构造函数 -> onCreate -> onStartCommand -> onStart -> onHandleIntent -> onDestroy

2、点击两次startService

  • 在onDestroy之前会回调service的 onStartCommand -> onStart

  • 在第一次任务的onHandleIntent执行完毕后,才开始执行第二次任务的onHandleIntent (顺序执行)

  • 所有任务都执行完毕后才执行onDestroy

IntentService源码解析

startService()是由系统来启动service的

1、onCreate()

  • 创建一个名为IntentService[xx]的handlerThread,并启动这个线程
  • 得到这个线程所对应Looper,并根据Looper创建对应的ServiceHandler,来处理message

2、onStartCommand() - > onStart() -> serviceHanlder.sendMessage()

3、通过Looper调度 -> serviceHandler.handleMessage() -> onHandleIntent()(需要子类实现的抽象方法)

public abstract class IntentService extends Service {
    private volatile Looper mServiceLooper;
    private volatile ServiceHandler mServiceHandler;
    private String mName;
    private boolean mRedelivery;

    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);
        }
    }

    public IntentService(String name) {
        super();
        mName = name;
    }
    
    public void setIntentRedelivery(boolean enabled) {
        mRedelivery = enabled;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        
        HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
        thread.start();

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

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

    @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();
    }

    @Override
    @Nullable
    public IBinder onBind(Intent intent) {
        return null;
    }

    @WorkerThread
    protected abstract void onHandleIntent(@Nullable Intent intent);
}

现在可以解释一下多次点击startService的执行过程了

  • 多次点击startService,onCreate只执行一次,但onStartCommand会回调多次,也就是说会通过serviceHandler发送多个message给serviceHandler;

  • 根据Looper.loop(),循环从MessageQueue中取出消息,回调serviceHandler的handleMessage(),也就是说会依次按顺序执行onHandleIntent()

  • 多次启动service不会重新创建新的服务和新的线程,只是把消息加入消息队列中等待执行,而如果服务停止,会清除消息队列中的消息,后续的事件得不到执行。

解答疑惑:

为什么每次onHanleIntent之后都会执行stopSelf(),为什么不会多次onDestroy() 呢?

因为stopSelf()会进行检查,只有等到所有任务都执行完成后才会真正的destroy

源码解释一波:

IntentService.java # stopSelf(msg.arg1)

//多次点击的startId是从1开始递增
Service.java # stopSelf(int startId)

ActivityManagerService.java # stopServiceToken(ComponentName className, IBinder token, int startId)

ActiveServices.java

 boolean stopServiceTokenLocked(ComponentName className, IBinder token,
            int 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; //就是这里啦。。。。。。
                }
            }
          //省略部分代码
            return true;
        }
        return false;
    }
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值