Android之IntentService

1.简单使用

tv.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(HandleActivity.this, MyIntentService.class);
                intent.putExtra("name", "jj");
                intent.putExtra("age", 15);
                startService(intent);
            }
        });
public class MyIntentService extends IntentService {
    public static final String TAG = "MyIntentService";

    public MyIntentService() {
        super(TAG);
        Log.d(TAG, "MyIntentService() is invoke "+Thread.currentThread().getId()+"="+Thread.currentThread().getName());
    }

    @Override
    public void onCreate() {
        super.onCreate();
        Log.d(TAG, "onCreate is invoke "+Thread.currentThread().getId()+"="+Thread.currentThread().getName());
    }

    @Override
    public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
        Log.d(TAG, "onStartCommand is invoke "+Thread.currentThread().getId()+"="+Thread.currentThread().getName());
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    protected void onHandleIntent(@Nullable Intent intent) {
        //做耗时操作
        Log.d(TAG, "onHandleIntent is invoke "+Thread.currentThread().getId()+"="+Thread.currentThread().getName());
        int age = intent.getIntExtra("age",0);
        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        Log.d(TAG, "age = "+age);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        Log.d(TAG, "onDestroy is invoke "+Thread.currentThread().getId()+"="+Thread.currentThread().getName());
    }
}

运行后的日志:

2019-03-12 14:03:09.138 18881-18881/com.ysl.myandroidbaseserver D/MyIntentService: MyIntentService() is invoke 2=main
2019-03-12 14:03:09.141 18881-18881/com.ysl.myandroidbaseserver D/MyIntentService: onCreate is invoke 2=main
2019-03-12 14:03:09.142 18881-18881/com.ysl.myandroidbaseserver D/MyIntentService: onStartCommand is invoke 2=main
2019-03-12 14:03:09.143 18881-18918/com.ysl.myandroidbaseserver D/MyIntentService: onHandleIntent is invoke 3270=IntentService[MyIntentService]
2019-03-12 14:03:19.144 18881-18918/com.ysl.myandroidbaseserver D/MyIntentService: age = 15
2019-03-12 14:03:19.148 18881-18881/com.ysl.myandroidbaseserver D/MyIntentService: onDestroy is invoke 2=main

可以看到它可以执行一个耗时任务在我们重写的onHandleIntent方法中;其它的几个方法因为它继承自service,所以都在主线程中进行;service中不能执行耗时任务,否则就会ANR;但是IntentService却可以,那它是怎么做到的呢?

2.看看IntentService的源码

首先开启一个服务会调用onCreate方法,我们看看它的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;并且把HandlerThread的looper传递给ServiceHandler;

我们再来看看ServiceHandler:

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((Intent)msg.obj);其实我们就是在这个方法中做的耗时任务。所以IntentService使用的还是handler机制,把任务从主线程挪到了子线程去执行了。并且执行完任务后,有调用了stopSelf(msg.arg1)方法;把服务停止了。

接下来看onStartCommand:

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

调用了onStart(intent, startId);把intent继续向下传递了;

接着看onStart方法:

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

这段代码就很熟悉了,构建了一个message对象,并把intent和startid包装好,发送了handler消息;这里就是我们上边分析的ServiceHandler;然后就在handleMessage中把intent传给了onHandleIntent((Intent)msg.obj);最后执行完任务把服务停止。

在onDestroy中调用:mServiceLooper.quit();把looper也退出了。

3.总结

IntentService其实内部使用的是:HandlerThread中的looper创建的一个ServiceHandler;通过ServiceHandler把intent发送到子线程进行处理业务。从而实现在service所在的主线程中把任务发送到子线程HandlerThread中进行处理。

IntentService会在任务执行完成后自行结束自己,而不需要外部去调用stopService了。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值