美文网首页
十、IntentService解析

十、IntentService解析

作者: 木小伍 | 来源:发表于2021-10-15 13:51 被阅读0次

    intentService是Android里面的一个封装类,继承自Service,用于异步请求,实现多线程。
    工作流程:


    intentService工作流程

    如果启动IntentService多次,那么每个耗时操作那么每个耗时操作则以队列的形式在intentService的onHandleIntent回调方法中依次执行,执行完自动结束。

    1.实现步骤

      1. 定义IntentService的子类:传入线程名称、复写onHandleIntent方法。
    • 2.在Manifest文件中注册
    • 3.在Activity中启动Service服务。

    2.具体实例

    1. 定义IntentService的子类
    public class MyIntentService extends IntentService {
        /**
         * 构造函数,传入的参数是工作线程的名称
         * @param
         */
        public MyIntentService() {
            super("wyw");
        }
    
       //实现耗时任务
        @Override
        protected void onHandleIntent(@Nullable Intent intent) {
            //根据intent的不同,进行不同的事务处理
            String taskName = intent.getExtras().getString("taksName");
            switch (taskName){
                case "taks1":
                    Log.i("MyIntentService", "task1");
                    break;
                case "task2":
                    Log.i("MyIntentService", "task2");
                    break;
                case "task3":
                    Log.i("MyIntentService", "task3");
                    break;
            }
        }
    }
    
    1. 在manifest文件中注册:
    <service android:name=".MyIntentService">
                <intent-filter>
                    <action android:name="com.wyw.service"/>
                </intent-filter>
     </service>
    
    1. 在activity中启动
            Intent intent  = new Intent("com.wyw.service");
            Bundle bundle = new Bundle();
            bundle.putString("taskName","task1");
            intent.putExtras(bundle);
            startService(intent);
    
            Intent intent2  = new Intent("com.wyw.service");
            Bundle bundle2 = new Bundle();
            bundle.putString("taskName","task2");
            intent2.putExtras(bundle2);
            startService(intent2);
            startService(intent); //多次启动
    

    运行结果


    多次启动IntentService结果

    3.源码分析

    • IntentService如何单独开启一个新的工作线程?
    //IntentService onCreate()方法
     @Override
        public void onCreate() {
       //HandlerThread继承自Thread,内部封装了Looper
       //通过实例化HandlerThread新建线程并启动
       //所以使用IntentService时不需要额外新建线程
            super.onCreate();
            HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");
            thread.start();
        //获得工作线程的Looper,并维护自己的工作队列
            mServiceLooper = thread.getLooper();
        //新建Hanler属于工作线程
            mServiceHandler = new ServiceHandler(mServiceLooper);
        }
    
        private final class ServiceHandler extends Handler {
            public ServiceHandler(Looper looper) {
                super(looper);
            }
          //IntentService的handleMessage方法把接收的消息交给onHandleIntent()处理。
          //onHandleIntent()是一个抽象方法,使用时需要重写的方法。
            @Override
            public void handleMessage(Message msg) {
                onHandleIntent((Intent)msg.obj);
                stopSelf(msg.arg1);
            }
        }
    
    • IntentService如何通过onStartCommand()传递给服务intent被依次插入到工作队列中?
        @Override
        public void onStart(@Nullable Intent intent, int startId) {
            Message msg = mServiceHandler.obtainMessage();
            msg.arg1 = startId;
            //把intent参数包装到message的obj中,然后发送消息,即添加到消息队列中
            //这里的intent就是启动服务时startService(Intent)的intent。
            msg.obj = intent;
            mServiceHandler.sendMessage(msg);
        }
        @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 onDestroy() {
            mServiceLooper.quit();
        }
    
    • 总结
      从源码可以看出,IntentService本质是采用Handler & HandlerThread方式:
      1. 通过HandlerThread单独开启一个名为IntentService 的线程。
      2. 创建一个名叫ServiceHandler的Handler。
      3. 把内部Handler与HandlerThread所对应的子线程进行绑定
      4. 通过onStartCommand()传递给服务intent,依次插入到工作队列中,并逐个发送给onHandleIntent()。
      5. 通过onHandleIntent()来依次处理所有Intent请求对象所对应的任务。

    因此我们通过复写onHandleIntent(),再根据Intent的不同进行不同进行不同的现场操作就可以了。
    注意:工作任务队列是顺序执行的。

    如果一个任务正在IntentService中执行,此时你再发送一个新的任务请求,这个新的任务会一直等待直到前面一个任务执行完毕才开始执行。

    原因:

    1. 由于onCreate()方法只会调用一次,所以只会创建一个工作线程;
    2. 当多次调用startService(Intent)时(onStartCommand也会调用多次)其实并会创建新的工作线程,只是把消息加入消息队列中等待执行,所以多次启动IntentService会按照顺序执行。
    3. 如果服务停止,会清除消息队列中的消息,后续的事件得不到执行。

    4.使用场景

    • 线程任务需要顺序、在后台执行的使用场景(离线下载)
    • 由于所有的任务都在同一个Thread looper里面来做,所以不符合多个数据同时请求的场景。

    相关文章

      网友评论

          本文标题:十、IntentService解析

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