IntentService源码分析—Android开发艺术探索笔记

概述

IntentService 是一个特殊的 Service,它继承了 Service 并且是一个抽象类,因此必须创建它的子类才能使用 IntentService。一般我们用 Service 在后台做一些耗时操作。这个时候我们需要在 Service 中开启子线程,也要管理 Service 的生命周期。IntentService 这个类的存在就是为了简化我们这些操作的。使用这个类,我们不需要自己去创建子线程,不需要手动管理 Service 的生命周期。

使用

我们用一个简单的例子看一下 IntentService 的使用方式。定义一个 IntentService 的子类 LocalIntentService:

public class LocalIntentService extends IntentService {
    private static final String TAG = "LocalIntentService";
    public static final String TASK_ACTION = "task_action";
    public LocalIntentService() {
        super(TAG);
    }

    @Override
    protected void onHandleIntent(Intent intent) {
        String action = intent.getStringExtra(TASK_ACTION);
        Log.d(TAG,"receive task : " + action);
        SystemClock.sleep(3000);
        if ("cc.action.TASK1".equals(action)) {
            Log.d(TAG,"handle task : " + action);
        }
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.d(TAG,"service destroyed");
    }
}

当我们继承 IntentService 的时候,我们必须重写 onHandleInten 方法,在这里我们会接收到起服务的 intent,在这里处理 intent。我们在这个方法里让线程休眠3秒模拟一个耗时操作。然后,我们在外界请求执行后台任务:

private void localService() {

    Intent intent = new Intent(this,LocalIntentService.class);
    intent.putExtra(LocalIntentService.TASK_ACTION,"cc.action.TASK1");
    startService(intent);

    Intent intent2 = new Intent(this,LocalIntentService.class);
    intent2.putExtra(LocalIntentService.TASK_ACTION,"cc.action.TASK2");
    startService(intent2);

    Intent intent3 = new Intent(this,LocalIntentService.class);
    intent3.putExtra(LocalIntentService.TASK_ACTION,"cc.action.TASK3");
    startService(intent3);
}

我们打印了收到任务的日志,task1处理的日志,最后打印了 Service 销毁的日志。我们看一下运行日志:

03-23 11:37:34.867 8178-8363/cc.handlerdemo D/LocalIntentService: receive task : cc.action.TASK1
03-23 11:37:37.869 8178-8363/cc.handlerdemo D/LocalIntentService: handle task : cc.action.TASK1
03-23 11:37:37.870 8178-8363/cc.handlerdemo D/LocalIntentService: receive task : cc.action.TASK2
03-23 11:37:40.872 8178-8363/cc.handlerdemo D/LocalIntentService: receive task : cc.action.TASK3
03-23 11:37:43.876 8178-8178/cc.handlerdemo D/LocalIntentService: service destroyed

从日志可以看出,三个任务是排队执行的,他们的执行顺序是和他们的发起顺序是一致的。当三个任务都执行完后才执行 onDestroy 方法。知道了它的用法之后,我们看看它的源码,理清它的实现原理。

源码分析

首先,看一下它的 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);
}

看到这里,我们心里应该有了一个大概。onCreate 方法里面出现了 HandlerThread 和 Handler。所以,IntentService 内部是封装了 HandlerThread 和 Handler。接着看一下 onStartCommand 方法:

@Override
public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
    onStart(intent, startId);
    return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
}

直接调用的 onStart 方法:

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

onStart 方法就做了一件事:发送一个消息。这个消息里面就包含了我们起服务发送的 intent。然后这个消息会发送给 HandlerThread 去处理:

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

handleMessage 方法调用了我们要实现的方法:onHandleIntent。这样我们的任务就到了子线程去处理,不需要我们new Thread 去处理我们的耗时操作,满足了我们的第一点。接着,onHandleIntent 方法执行完后会执行 stopSelf(int startId) 方法来尝试停止服务。为什么不直接使用 stopSelf()方法呢?因为调用 stopSelf()会立刻停止服务,而这个时候可能还有消息没有处理,stopSelf(int startId)则会等待所有消息都处理完毕才会终止服务。在尝试停止服务的时候会判断最近启动服务的次数是否和 startId 相等。如果相等就停止服务,否则不停止。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值