Android IntentService最直白的解析

我们都知道Android消息机制是可以用来执行异步任务,而上一篇 Android HandlerThread最直白的解析 中,我们又聊过了HandlerThread,那么现在我们就来聊聊Android多线程中另一种常见的用法 IntentService,其内部线程的切换实质就是用 HandlerThread 来实现的。


首先用一段很直白的话来简单总结下什么是 IntentService及它的作用与使用场景:

  1. IntentService是一个继承了Service的抽象类,有较高的优先级;
  2. 开发者使用它能很方便的在后台执行耗时的异步任务,并且当任务完成后会自动停止;
  3. 使用IntentService执行的异步任务是按顺序执行的,其本身并不支持并发需求。

按照惯例,我们来看看官网对IntentService的介绍:

IntentService is a base class for Services that handle asynchronous requests (expressed as Intents) on demand. Clients send requests through Context.startService(Intent) calls; the service is started as needed, handles each Intent in turn using a worker thread, and stops itself when it runs out of work.

All requests are handled on a single worker thread -- they may take as long as necessary (and will not block the application's main loop), but only one request will be processed at a time.


IntentService是一个服务的基类,根据Intent的需求来处理异步请求。客户端通过调用 Context.startService(Intent) 发送请求。该服务使用一个工作线程来处理每个 Intent ,并且当它完成工作时会自动停止。

所有请求都是在一个工作线程上处理的,它们也许会需要很长时间(不会阻塞应用程序的主线程),但是一次只能处理一个请求。 


首先来看看IntentService的常规使用:

新建一个IntentService的子类

public class IntentServiceTest extends IntentService {

    //在构造函数中传入线程名字
    public IntentServiceTest() {
        this("defaultIntentService");
    }


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

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

    /**
     * 重写onHandleIntent方法
     * 这个方法运行在子线程
     * 根据不同的intent 执行耗时任务
     *
     * @param intent
     */
    @Override
    protected void onHandleIntent(@Nullable Intent intent) {
        int flag = intent.getIntExtra("flag", 0);
        switch (flag) {
            case 0:
                //执行传入intent flag为0时的操作
                Log.e("sheep", "flag=" + flag);
                break;
            case 1:
                //执行传入intent flag为1时的操作
                Log.e("sheep", "flag=" + flag);
                break;
            //...
            default:
                break;
        }
    }

    @Override
    public void onDestroy() {
        Log.e("sheep","onDestory");
        super.onDestroy();
    }
}

在Activity中开启Service服务

    private void init() {
        Intent intent=new Intent(this,IntentServiceTest.class);
        intent.putExtra("flag",0);
        startService(intent);
        intent.putExtra("flag",1);
        startService(intent);
        intent.putExtra("flag",0);
        startService(intent);

        btn0.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent=new Intent(IntentServiceActivityTest.this,IntentServiceTest.class);
                intent.putExtra("flag",0);
                startService(intent);
            }
        });

    }

我们在执行了init() 方法后,又点击了一次btn0,运行结果如下

运行结果

可以看到根据不同的Intent,我们在onHandleIntent() 方法中分别执行了相应操作,同时当任务执行完成后,IntentService就自尽了,所以走到了onDestory() ,再点击一次btn0时,就会重新走oncreate()。是不是觉得特别简单,其实IntentService的使用就分为三步:

  1. 创建一个 IntentService的子类,传入线程的名称,同时重写onHandleIntent() 方法,根据传入不同的Intent ,执行相应的异步操作;

  2. 在Manifest.xml中注册此service;

  3. 在 Activity 中开启此 Service 服务。


现在我们来看一看IntentService的源码,探求一下其中原理,其实也挺简单的:

public abstract class IntentService extends Service {
    private volatile Looper mServiceLooper;
    private volatile ServiceHandler mServiceHandler;
    private String mName;
    private boolean mRedelivery;
    
    //定义IntentService内部的Handler
    private final class ServiceHandler extends Handler {
        public ServiceHandler(Looper looper) {
            super(looper);
        }

        @Override
        public void handleMessage(Message msg) {
            //调用此方法处理异步任务
            onHandleIntent((Intent)msg.obj);
            //完成任务后自尽
            //这里重点解释下,stopSelf()此方法接收的id即是启动服务时,ActivityManager分配的
            //id,当结束服务时会比对该id是否和最新启动该服务的id一致,只有当比对一致时才会结束掉
            //自己,所以说只有当最后一次startService(intent)启动的服务中onHandleIntent()方
            //法执行完毕时才会自尽。
            stopSelf(msg.arg1);
        }
    }

    
    //子类重写构造函数需要传入一个字符串作为工作线程名称
    public IntentService(String name) {
        super();
        mName = name;
    }

      
    //如果传入true,则onStartCommand()方法将返回 Service.START_REDELIVER_INTENT,这样当
    //服务被kill时,系统会自动重启该服务,并将Intent的值传入。(如果有多个 Intent,只会使用最后
    //的一个);如果传入false,则onStartCommand()方法将返回 Service.START_NOT_STICKY,“非粘
    //性的”。使用这个返回值时,如果在执行完onStartCommand后,服务被异常kill掉,系统不会自动重启
    //该服务。
    public void setIntentRedelivery(boolean enabled) {
        mRedelivery = enabled;
    }

    
    @Override
    public void onCreate() {

        super.onCreate();
        //服务创建时,会启动一个HandlerThread
        HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
        thread.start();
        //创建一个Handler,只有handlerThread中的Looper,则轮循在子线程中
        mServiceLooper = thread.getLooper();
        mServiceHandler = new ServiceHandler(mServiceLooper);
    }

    @Override
    public void onStart(@Nullable Intent intent, int startId) {
        //将 intent 和 startId 赋值在消息中,通过handler来发送
        Message msg = mServiceHandler.obtainMessage();
        msg.arg1 = startId;
        msg.obj = intent;
        mServiceHandler.sendMessage(msg);
    }

    /**
     * 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;
    }

    @Override
    public void onDestroy() {
        //销毁时退出Looper的轮循
        mServiceLooper.quit();
    }

    /**
     * Unless you provide binding for your service, you don't need to implement this
     * method, because the default implementation returns null.
     * @see android.app.Service#onBind
     */
    @Override
    @Nullable
    public IBinder onBind(Intent intent) {
        return null;
    }

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

具体分析在代码中都已经注释了,仔细看看挺简单的,其实IntentService的本质也就是 HandlerThread + Handler:

  1. 通过HandlerThread 单独开启1个工作线程;
  2. 使用HandlerThread的Looper创建了一个Handler,此Handler便可以执行异步任务;
  3. 在onStartCommand() 方法中将 intent 和 startId 赋值在消息中,通过Handler来发送,依次插入到工作队列中逐个发送给onHandleIntent() ;
  4. 在onHandleIntent() 中依次处理不同Intent 所对应的任务。

至此,IntentService 的使用和源码我们就都分析完了,有一点需要注意的是 onHandleIntent() 中任务的执行是和启动服务的顺序一致的。

再次使用文章开头的总结:IntentService是有着较高优先级的Service,能顺序执行异步任务,同时当完成任务时会自尽。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值