美文网首页Android性能
Android IntentService使用介绍以及原理分析

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

作者: dashingqi | 来源:发表于2019-05-16 00:14 被阅读0次

    简介

    • 在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使用介绍以及原理分析

        本文链接:https://www.haomeiwen.com/subject/ygdvaqtx.html