Android进阶知识:IntentService相关

1,527 阅读4分钟

1.前言

Android基础知识:多线程基础总结中除了AsyncTaskHandlerThread还提到了Android提供的另外一种进行异步任务的方式IntentService。这一篇就来看看IntentService的使用和运行原理。

2.IntentService的使用

IntentService的使用步骤分为以下几步:

1.继承实现IntentService抽象类,复写onHandleIntent方法

public class MyIntentService extends IntentService {
    private static final String TAG = "MyIntentService";
    private int percent;
    public MyIntentService() {
        super("MyIntentServiceThread");
    }
    @Override
    protected void onHandleIntent(Intent intent) {
        String type = intent.getStringExtra("type");
        switch (type) {
            case "type1":
            {
                for (percent = 0; percent <= 100; percent += 10) {
                    try {
                        Thread.sleep(300);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    Log.d(TAG, Thread.currentThread().getName() + " type1  " + percent + "% progress");

                }
                Log.d(TAG, Thread.currentThread().getName() + ":finish");
            }
            break;
        }
    }
}

2.在AndroidManifest.xml注册Service

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.thread.intentservice">
    <application
        .......
        <service android:name=".MyIntentService" />
    </application>

</manifest>

3.启动IntentService服务

Intent intent = new Intent(this, MyIntentService.class);
intent.putExtra("type", "type1");
startService(intent);

运行结果:

3.IntentService运行原理

从使用方法上来看IntentService与一般的Service使用步骤也没啥区别,都是先创建实现一个Service再到AndroidManifest.xml中注册,最后启动服务即可。那么还是从源码看看IntentService到底有什么特别的地方。

  public abstract class IntentService extends Service {
    .......
    /**
     * Creates an IntentService.  Invoked by your subclass's constructor.
     *
     * @param name Used to name the worker thread, important only for debugging.
     */
    public IntentService(String name) {
        super();
        mName = name;
    }

首先看到IntentService是个抽象类,并且继承自Service,它的构造函数中只传入了name,从注释看出就是工作线程的name。既然是个Service接着就看它生命周期中的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
        HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
        // 调用HandlerThread的start方法开启线程
        thread.start();
        // 获得HandlerThread中的Looper
        mServiceLooper = thread.getLooper();
        // 创建Handler
        mServiceHandler = new ServiceHandler(mServiceLooper);
    }

onCreate方法中的代码看着有些熟悉就是之前在Android进阶知识:HandlerThread相关中提到的HandlerThread的使用步骤。所以说在onCreate方法中就是创建了一个HandlerThread的工作线程,调用了它的start方法并且创建了对应Handler。先来看一下这个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);
        }
    }

ServiceHandlerIntentService的内部类,其实现也很简单,接收了传入的Looper后复写handleMessage方法,handleMessage方法中收到消息后先调用了onHandleIntent方法将intent传入。onHandleIntent方法是我们自己实现IntentService时复写的方法,源码这里是个抽象方法,主要进行异步耗时任务,然后调用stopSelf将自身关闭。

protected abstract void onHandleIntent(@Nullable Intent intent);

接着继续按生命周期走到了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 onStart(@Nullable Intent intent, int startId) {
        Message msg = mServiceHandler.obtainMessage();
        msg.arg1 = startId;
        msg.obj = intent;
        mServiceHandler.sendMessage(msg);
    }
    

onStartCommand方法中又调用了onStart方法,而onStart方法创建了消息,并且将接收到的intent作为消息的objstartId传递给消息arg1,最后调用mServiceHandler.sendMessage将消息发送出去。到此整个IntentService的运行流程就差不多了,最后在调用stopSelf方法后服务会调用生命周期中的onDestory方法,在IntentServiceonDestory方法中会直接调用mServiceLooper.quit()方法将Lopper退出。

另外IntentService中还有个mRedelivery成员变量可以通过setIntentRedelivery方法设置,用来决定onStartCommand方法的返回值,从而决定服务在被异常杀死后是否自动重启该服务。

// 布尔值变量
private boolean mRedelivery;
// setIntentRedelivery方法
public void setIntentRedelivery(boolean enabled) {
        mRedelivery = enabled;
}
// onStartCommand返回值
@Override
public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
        onStart(intent, startId);
        return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
}

4.总结

从上面的阅读的源码可以知道IntentService实现异步任务是基于HandlerThread实现的。

IntentService的运行流程: 启动服务后会先进行生命周期的onCreate方法,方法中创建HandlerThreadServiceHandler,接着进入生命周期的onStartCommand方法,onStartCommand方法中调用onStart方法,onStart方法使用ServiceHandler发送消息,handleMessage方法中接收到消息,调用复写的onHandleIntent方法,最后调用stopSelf方法关闭自己。

IntentService与普通Service对比:

普通Service IntentService
运行在主线程 运行在创建的工作线程
需要手动调用stopService关闭 自动调用stopSelf关闭