IntentService源码分析

IntentService继承了Service并且是一个抽象类,需要创建它的子类才能使用IntentService。它相对Service来说,是一个特殊的Service,它的内部使用HandleThread

来执行服务,任务执行完,IntentService会自动退出。相对于Thread来说,它是一个服务,它的优先级高于线程,不容易被系统回收。

一个面试问题:我要用服务下载apk,是用IntentService,还是Service好?为什么?

IntentService与Service都可以执行下载apk的任务。具体的下载代码可以观看我的文章:IntentService、Service下载的apk。在回答这可问题之前我们要再次回顾一下Service的概念。Service是一种计算型组件,用于在后台执行一系列计算任务。Service不是一个线程,尽管它是执行后台计算的,它是运行在主线程中,耗时的后台操作仍然需要在单独的子线程中去执行,所以不要在Service的onStart方法中执行耗时操作,不然会出现Application Not Responding!的异常。而IntentService采用队列的方式将请求的Intent加入队列,然后开启一个线程来处理队列中的Intent,对于异步的startService请求。IntentService处理完一个后再处理第二个,都是在子线程中,不会阻塞主线程。所以有耗时操作与其在Service里开启子线程不如在IntentService中处理耗时操作。

回到主题,继续分析IntentService。

在IntentService的onCreate()方法中,可以看到它实现了HandleThread 和Handle。

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

IntentService第一次启动时,onCreate()方法调用,创建一个HandlerThread,获取到mServiceLooper,mServiceHandler。通过mServiceHandler发送信息会在HandlerThread中执行。每次启动IntentService,会调用onStartCommand()。IntentService在onStartCommand()方法中处理后台的Intent。在源码中onStartCommand调用了onStart():

 @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 onStart(@Nullable Intent intent, int startId) {
        Message msg = mServiceHandler.obtainMessage();
        msg.arg1 = startId;
        msg.obj = intent;
        mServiceHandler.sendMessage(msg);
    }

IntentService通过mServiceHandler发送了一条信息,消息会在HandleThread方法中处理。同时将Intent对象给 ServiceHandler的onHandleIntent方法处理。onHandleIntent是运行在子线程中,可以做耗时操作。另外这里的Intent对象和外界startService(intent)保持一致,通过它可以获得外界启动IntentService传递的参数,可以区分具体的后台任务,对不同的后台采取不同的处理方式(可以咱参照文章后边的样例)。onHandleIntent方法执行完之后,会调用stopSelf(int startId)停止服务。stopSelf()会立即停止服务,stopSelf(int startId)会等待所有信息都处理完后才关闭服务,它在服务关闭前会判断最近启动的次数是否与startId相等,相等立即停止服务,不相等不停止服务。

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

//This method is invoked on the worker thread with a request to process.
  @WorkerThread
    protected abstract void onHandleIntent(@Nullable Intent intent);

onHandleIntent是一个抽象方法,需要在子类中实现,它的作用就是区分Intent中的参数来区分任务并执行。在执行完onHandleIntent方法后,如果目前只有一个后台任务会立刻调用stopSelf(int startId)停止服务。如果有多个,会在onHandleIntent执行完最后一个任务后调用停止服务。每执行一个后台任务都会启动一次IntentService,而IntentService内部的信息是通过HandleThread来执行,Handle中的Looper顺序处理信息,所以IntentService是顺序执行后台任务的。多后台任务会按照外界发起的顺序排队执行。

public class DemoIntentService extends IntentService {

    static final String Tag = "DemoIntentService";

    public DemoIntentService() {
        super("demo-intentService");
    }

    @Override
    protected void onHandleIntent(Intent intent) {
        String action = intent.getStringExtra("test_action");
        Log.e(Tag, "receive action=====" + action);
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onDestroy() {
        Log.e(Tag, "onDestroy=====");
        super.onDestroy();
    }
}
public class TestActivity extends Activity {

    BroadcastReceiver receiver;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
Intent mIntent = new Intent(this, DemoIntentService.class);
        mIntent.putExtra("test_action","action1");
        startService(mIntent);
        mIntent.putExtra("test_action","action2");
        startService(mIntent);
        mIntent.putExtra("test_action","action3");
        startService(mIntent);
    }

}
注册列表
<service android:name=“.downloadApk.DemoIntentService"/>

打印结果:

05-16 23:53:12.219 18007-18292/? E/DemoIntentService: receive action=====action1

05-16 23:53:13.219 18007-18292/? E/DemoIntentService: receive action=====action2

05-16 23:53:14.219 18007-18292/? E/DemoIntentService: receive action=====action3

05-16 23:53:15.219 18007-18007/? E/DemoIntentService: onDestroy=====

日志显示三个后台任务顺序执行,在action3后,执行stopSelf(int startId)。

=====================================>

这是一篇对书笔记,文章内容大多数来自于androdi开发艺术探索,很不错的一本书。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值