Android IntentService使用介绍以及原理分析

简介

  • 在Android应用的程序中,普通的Service中的代码是运行在主线程中的,如果想要在Service中做些耗时的操作,就很容易出现ANR的现象(大概是20秒),那么我们经常的做法就是,在onStartCommon方法中开启一个子线程然后内部执行耗时的操作,在执行完毕后如果需要自动停止服务需要在子线程的run方法中调用stopSelf()来停止服务。
  • 虽说在Service中执行耗时的代码可以很容易的实现,但是Android提供的IntentService类可以很方便的解决了自己开启线程和手动停止服务的问题。接下来看看IntentService的使用步骤。

使用步骤

  • IntentService是一个抽象类内部有一个抽象的方法 handleIntent(),继承至Service类.所以使用它需要继承它实现抽象方法。
      public class MyIntentService extends IntentService {
      private static final String TAG = "MyIntentService";
      public MyIntentService() {
          super("MyIntentService");
      }
    
      @Override
      protected void onHandleIntent(Intent intent) {
          //在这里通过intent携带的数据,开进行任务的操作。
          Log.d(TAG, "onHandleIntent: " + Thread.currentThread().getName());
      }
    
      @Override
      public void onDestroy() {
          super.onDestroy();
          Log.d(TAG, "onDestroy: ");
        }
    }
    
  • 然后调用StartService()启动异步后台服务类 IntentService。
      startService.setOnClickListener(new View.OnClickListener() {
              @Override
              public void onClick(View v) {
                  Intent intent = new Intent(MainActivity.this, MyIntentService.class);
                  startService(intent);
              }
          });
    

源码分析

  • 服务启动的过程中,会去执行服务的生命周期方法,在开启服务的时候,有两种方式,分别为startService和bindService
  • startService方式启动,生命周期方法执行的顺序是 onCreate(),onStartCommand() onStart() onDestroy(),按照生命周期执行顺序我们查看IntentService的源码
   // onCreate方法的分析
    @Override
   public void onCreate() {
       super.onCreate();
       HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
       //创建了一个Looper对象 & MessageQueue对象 调用了Looper.loop方法
       thread.start();
       //   获取到HandlerThread中创建好的Looper对象。
       mServiceLooper = thread.getLooper();
       //ServiceHandler extends Handler,绑定了HandlerThread中的Looper对象 ;那个线程调用了Looper中的loop方法,Handler的dispatchMessage方法就运行在那个线程中。
       mServiceHandler = new ServiceHandler(mServiceLooper);
   }
 //onStartCommand()方法分析
  public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
       // 调用了onStart方法
       onStart(intent, startId);
       return mRedelivery ? START_REDELIVER_INTENT : START_NOT_STICKY;
   }
//onStart方法
public void onStart(@Nullable Intent intent, int startId) {
       //在这里构造了一个消息对象
       Message msg = mServiceHandler.obtainMessage();

       msg.arg1 = startId;
       //将intent 包装到了Message的obj中,
       msg.obj = intent;
       //然后调用sendMessage()将消息插入到队列中。
       //最终消息被取出然后被分发,最后调用了handleMessage()来处理这个消息
       mServiceHandler.sendMessage(msg);
   }
   //ServiceHandler handleMessage方法的分析
   private final class ServiceHandler extends Handler {
       public ServiceHandler(Looper looper) {
           super(looper);
       }

       @Override
       public void handleMessage(Message msg) {
           //SeriviceHandler 的handleMessage()方法中 将接受到的消息交给onHandleIntent来处理,onHandleIntent方法就是我们实现的方法,获取到Intent,处理任务。
           onHandleIntent((Intent) msg.obj);
           //执行完 结束服务
           stopSelf(msg.arg1);
       }
   }
  // onDestroy()方法的处理
  @Override
   public void onDestroy() {
       //将消息队列中的所有消息给移除,包括处理中的和未处理的
       mServiceLooper.quit();
   }

总结说来就是,开启服务执行onCreate()方法,方法中创建好了一个子线程(HandlerThread),(子线程中创建好了一个Looper对象同时创建好了一个MessagqQueue消息队列,然后开启轮询消息队列。),内部创建好的Handler与子线程中的Looper对象绑定。onCreate只有在服务第一次创建的时候才会调用,之后每次调用都只会执行onStartCommand方法,在此方法中我们构建好了一个Message对象,并且将传递进来的Intent封装在Mesage,一起发送到消息队列中。经过轮询将消息分发到Handler的handleMessage中处理,此时获取到Message中携带的Intent传递给我们实现好的handleIntent方法中进行任务的处理,处理完毕自动调用StopSlef来结束服务。在onDestroy方法会把所有消息都给退出。

  • 上文中我们分析了startService方法启动的服务,那bindService方式启动服务的分析如下(绑定服务,建立长期通信),bindService启动会执行 onCreate -> onBind -> onUnBind -> onDestroy方法。
 //onCreate方法上文中已经分析
 //onBind()
  public IBinder onBind(Intent intent) {
       //直接返回null了。那么不对会Mesage对象和发送消息到队列中,
       //然后回调handleIntent方法了。
       return null;
   }

所以bindService方式启动服务,不会进行多线程的操作。

问题记录

简单描述一下IntentService
  • IntentService是一个特殊的Service类,是实现了多线程处理异步请求的一个服务类,在handleIntent方法中进行耗时的操作,如果有多个耗时的操作任务,会按照顺序去一个一个的执行,执行完一个关闭一个。
在源码handleMessage方法中为什么执行完handleIntent方法会去调用带参数的stopSelf()
  • 因为stopSelf()的执行会立刻将服务停止掉,而带参数的stopSelf(int startId)会在所有任务执行完毕后将服务给停止。通常情况下调用stopSelf(int satrtId)方法不会立刻去执行停止服务的操作,会去判断最近执行任务的次数是否和startId相等,如果相等就立刻执行停止服务的操作。

你可能感兴趣的:(Android IntentService使用介绍以及原理分析)