IntentService简介&源码分析

简介

IntentService 是一个继承自Service的抽象类,本质上还是一个Service,我们需要创建它的子类去使用。 IntentService 同时实现了 HandlerThread ,在内部维护了一个 WorkerThread 线程,专门用来处理耗时操作。实际上 IntentService 中所有的操作都是在这个 WorkerThread 中执行的。
多次启动同一个IntentService,则每一次启动的耗时任务,都会以消息队列的形式在WorkerThread中被依次执行,任务的执行是在onHandleIntent()方法中完成的。都执行完成后,就会调用 stopSelf() 自动结束,不需要我们去手动结束

优点

1. 优先级比较高,被杀死的几率低:
本质上 IntentService 也是开启了一个子线程,但是  IntentService 是继承自 Service 的,所以根据 Android系统Kill App的机制,使用  IntentService 的应用优先级更高一些。通俗点说,如果使用 IntentService 做为后台任务,当程序退到后台时,被杀死的几率会更低。
2.自动调用stopSelf()方法结束:
IntentService 会在任务执行完成后,自行结束,不需要外部调用 stopService();

缺点

由于 IntentService 里面维护的是一个 HandlerThread,里面的异步任务都是保存在队列里面的,因此 只能实现 单线程-多任务-同步执行 ,对于想要实现多线程并发的业务需求,这个不适合。 

特点

1.内部创建独立线程 WorkerThread ,来处理所有的 Intent 请求。
2.内部创建独立线程 WorkerThread ,来处理 onHandleIntent() 里面的耗时逻辑,无需担心多线程的问题。
3.所有的耗时任务完成之后,IntentService 调用 stopSelf() 自动停止。
4. 不能使用 bindService() 来绑定一个 IntentService
5.onBInd()方法返回null,也无需关心。
6. onStartCommand() 提供了默认的实现,会将请求的Intent任务添加到队列中

如何使用

IntentService 类似于一个单例,多次启动同一个IntentService类,onCreate() 只执行一次,
onStart / onStartCommand 的执行次数 = 启动次数,onHandleIntent() 方法会依次执行队列中的intent 任务。
public class MyService extends IntentService {
    //这里必须有一个空参数的构造实现父类的构造,否则会报异常
    //java.lang.InstantiationException: 
    //java.lang.Class<***.MyService> has no zero argument constructor
    public MyService() {
        super("");
    }
    
    @Override
    public void onCreate() {
        System.out.println("onCreate");
        super.onCreate();
    }

    @Override
    public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
        System.out.println("onStartCommand");
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void onStart(@Nullable Intent intent, int startId) {
        System.out.println("onStart");
        super.onStart(intent, startId);
    }

    @Override
    public void onDestroy() {
        System.out.println("onDestroy");
        super.onDestroy();
    }

    //这个是IntentService的核心方法,它是通过串行来处理任务的,也就是同步处理
    @Override
    protected void onHandleIntent(@Nullable Intent intent) {
        System.out.println("工作线程是: "+Thread.currentThread().getName());
        String task = intent.getStringExtra("task");
        System.out.println("任务是 :"+task);
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Intent intent = new Intent(this,MyService.class);
        intent.putExtra("task","播放音乐");
        startService(intent);
        intent.putExtra("task","播放视频");
        startService(intent);
        intent.putExtra("task","播放图片");
        startService(intent);
    }
}

源码分析   

// IntentService 的 onCreate() 方法,内部启动了一个 HandlerThread 线程。
@Override
public void onCreate() {
   super.onCreate();
   //HandlerThread 就是一个带有 handler 的 thread ,这里就是创建了一个线程,
   //注意这个线程的名字上面的日志打印中"工作线程是: IntentService[]"
   //因为我们在自定义的MyService里面,构造方法写的是super(""),如果写的不是空串,
   //上面的日志打印就应该是"工作线程是: IntentService[我们定义的名称]"
   HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
   thread.start();
   //获取这个线程的looper
   mServiceLooper = thread.getLooper();
   //创建了一个handler
   mServiceHandler = new ServiceHandler(mServiceLooper);
}
//我们来看一下 ServiceHandler 对消息的处理
private final class ServiceHandler extends Handler {
    public ServiceHandler(Looper looper) {
        super(looper);
    }
    @Override
    public void handleMessage(Message msg) {
        //处理逻辑是我们在MyService里面重写的这个方法
        onHandleIntent((Intent)msg.obj);
        //从这里可以看出,我们执行完任务后,service就销毁了
        stopSelf(msg.arg1);
    }
}
// 在onStart() 方法里发出了消息。
@Override
public void onStart(@Nullable Intent intent, int startId) {
    Message msg = mServiceHandler.obtainMessage();
    msg.arg1 = startId;
    msg.obj = intent;
    mServiceHandler.sendMessage(msg);
}

注意事项

1.为什么不能通过 bindService启动IntentService?
因为,bindService启动时,就不会执行onStartCommand() 方法,就会导致 OnHandleIntent() 不会被调用,这样一来,就和普通的Service 没什么区别了。
2.为什么多次启动 IntentService 会顺序执行事件?
IntentService 中使用的 Handler、Looper、MessageQueue 机制把消息发送到线程中去执行的,
所以多次启动 IntentService 不会重新创建新的服务和新的线程,只是把消息加入消息队列中等待执行。
3.停止服务后,后续的事件得不到执行?
如果服务停止,会调用Looper.quit()方法,清除消息队列中的消息,后续的事件就得不到执行了。
@Override
public void onDestroy() {
    mServiceLooper.quit();
}

猜你喜欢

转载自blog.csdn.net/m0_49508485/article/details/127255191