Android IntentService 使用

01.使用步骤

  • 步骤1:定义IntentService的子类:传入线程名称、复写onHandleIntent()方法
  • 步骤2:在Manifest.xml中注册服务
  • 步骤3:在Activity中开启Service服务

02.具体案例

  • 步骤1:定义IntentService的子类:传入线程名称、复写onHandleIntent()方法

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    /**
    * 初始化工作,子线程,处理耗时操作和避免在application做过多初始化工作,比如初始化数据库等等
    */
    @SuppressLint("Registered")
    public class InitializeService extends IntentService {

    private static final String ACTION_INIT = "initApplication";

    public static void start(Context context , String name) {
    Intent intent = new Intent(context, InitializeService.class);
    intent.setAction(ACTION_INIT);
    intent.putExtra("name",name);
    context.startService(intent);
    }

    /**
    * 在构造函数中传入线程名字
    **/
    public InitializeService(){
    //调用父类的构造函数
    //构造函数参数=工作线程的名字
    super("InitializeService");
    }

    @Override
    protected void onHandleIntent(Intent intent) {
    if (intent != null) {
    final String action = intent.getAction();
    String name = intent.getStringExtra("name");
    Log.e("IntentService初始化","onHandleIntent----"+name);
    if (ACTION_INIT.equals(action)) {
    initApplication();
    }
    }
    }

    @Override
    public void onCreate() {
    super.onCreate();
    Log.e("IntentService初始化","onCreate");
    }

    private void initApplication() {
    //处理耗时操作和避免在application做过多初始化工作,比如初始化数据库等等
    Log.e("IntentService初始化","initApplication");
    try {
    Thread.sleep(2000);
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    }

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

    @Override
    public void onDestroy() {
    super.onDestroy();
    Log.e("IntentService销毁","onDestroy");
    }
    }
  • 步骤2:在Manifest.xml中注册服务

    1
    <service android:name=".InitializeService"/>
  • 步骤3:在Activity中开启Service服务。

    1
    2
    3
    //同一服务只会开启一个工作线程
    //在onHandleIntent函数里依次处理intent请求。
    InitializeService.start(this,"yc"+i);

03.打印日志

  • 多次开启,打印日志如下

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    2019-05-23 11:57:51.032 20012-20012/cn.ycbjie.ycthreadpool E/IntentService初始化: onCreate
    2019-05-23 11:57:51.033 20012-20012/cn.ycbjie.ycthreadpool E/IntentService初始化: onStartCommand
    2019-05-23 11:57:51.034 20012-20356/cn.ycbjie.ycthreadpool E/IntentService初始化: onHandleIntent----yc8
    2019-05-23 11:57:51.034 20012-20356/cn.ycbjie.ycthreadpool E/IntentService初始化: initApplication
    2019-05-23 11:57:51.224 20012-20012/cn.ycbjie.ycthreadpool E/IntentService初始化: onStartCommand
    2019-05-23 11:57:51.439 20012-20012/cn.ycbjie.ycthreadpool E/IntentService初始化: onStartCommand
    2019-05-23 11:57:53.037 20012-20356/cn.ycbjie.ycthreadpool E/IntentService初始化: onHandleIntent----yc9
    2019-05-23 11:57:53.037 20012-20356/cn.ycbjie.ycthreadpool E/IntentService初始化: initApplication
    2019-05-23 11:57:55.041 20012-20356/cn.ycbjie.ycthreadpool E/IntentService初始化: onHandleIntent----yc10
    2019-05-23 11:57:55.041 20012-20356/cn.ycbjie.ycthreadpool E/IntentService初始化: initApplication
    2019-05-23 11:57:57.045 20012-20012/cn.ycbjie.ycthreadpool E/IntentService销毁: onDestroy
  • 如果启动IntentService多次,会出现什么情况呢?

    • IntentService多次被启动,那么onCreate()方法只会调用一次,所以只会创建一个工作线程。但是会调用多次onStartCommand方法,只是把消息加入消息队列中等待执行
  • 多次开启intentService,那为什么工作任务队列是顺序执行的?

    • 结论:如果一个任务正在IntentService中执行,此时你再发送一个新的任务请求,这个新的任务会一直等待直到前面一个任务执行完毕才开始执行。
    • 分析:
        1. 由于onCreate() 方法只会调用一次,所以只会创建一个工作线程;
        1. 当多次调用 startService(Intent) 时(onStartCommand也会调用多次)其实并不会创建新的工作线程,只是把消息加入消息队列中等待执行,所以,多次启动 IntentService 会按顺序执行事件
        1. 如果服务停止,会清除消息队列中的消息,后续的事件得不到执行。

04.IntentService作用

  • IntentService的介绍
    • IntentService是自己维护了一个线程,来执行耗时的操作,然后里面封装了HandlerThread,能够方便在子线程创建Handler。
    • IntentService是继承自Service用来处理异步请求的一个基类,客户端startService发送请求,IntentService就被启动,然后会在一个工作线程中处理传递过来的Intent,当任务结束后就会自动停止服务。
  • IntentService的作用
    • 开启多线程
    • 执行异步请求逻辑
  • IntentService 有以下几个特性:
    • IntentService 内部创建了一个工作线程,用于在子线程内执行传递给 onStartCommand() 的所有 Intent,开发者无须关心多线程问题
    • IntentService 内部通过 HandlerThread 和 Handler 来实现异步操作
    • IntentService 是以串行方式处理外部传递来的任务,即只有当上一个任务完成时,新的任务才会被执行
    • 在处理完所有任务请求后会自动停止,因此不必手动调用 stopSelf() 方法
    • 提供了 onBind() 的默认实现(返回 null)
    • IntentService 是四大组件之一,拥有较高的优先级,不易被系统杀死,因此适合于执行一些高优先级的异步任务

05.IntentService使用场景

  • IntentService不需要我们自己去关闭Service,它自己会在任务完成之后自行关闭,不过每次只能处理一个任务,所以不适用于高并发,适用于请求数较少的情况。
  • 例如播放音乐、下载文件等,但 Service 默认是运行于 UI 线程的,如果想要依靠其来完成一些耗时任务,就需要自己来建立子线程,这相对比较繁琐,所以官方也为开发者提供了 IntentService 来解决这一问题
  • 1.类似于APP的版本检测更新,后台定位功能以及读取少量的IO操作。
  • 2.线程任务需按顺序、在后台执行,比如阿里云推送的服务service就是继承IntentSerVice
  • 3.将部分application初始化的逻辑放到intentService里面处理,可以提高application启动时间
1
2
目前,由于正式项目中application初始化工作太多,所以决定分担部分逻辑到IntentService中处理
比如:现在application初始化内容有:数据库初始化,阿里云推送初始化,腾讯bugly初始化,im初始化,神策初始化,内存泄漏工具初始化,头条适配方案初始化,阿里云热修复……等等。将部分逻辑放到IntentService中处理,可以缩短很多时间。