Android Service详解(一)

作者: cff70524f5cf | 来源:发表于2019-03-22 21:50 被阅读24次

    Service系列一共2篇,主要介绍Service相关的使用,以及使用Service实现IPC通信。本文的重点是介绍Service相关的使用,通过Service 实现IPC通信放在下一篇讲解。

    What is a Service

    根据官方的介绍:

    1. Service既不是一个线程,Service通常运行在当成宿主进程的主线程中,所以在Service中进行一些耗时操作就需要在Service内部开启线程去操作,否则会引发ANR异常。
    2. 也不是一个单独的进程。除非在清单文件中声明时指定进程名,否则Service所在进程就是application所在进程。

    Service存在的目的有2个:

    1. 告诉系统,当前程序需要在后台做一些处理。这意味着,Service可以不需要UI就在后台运行,不用管开启它的页面是否被销毁,只要进程还在就可以在后台运行。可以通过startService()方式调用,这里需要注意,除非Service手动调用stopService()或者Service内部主动调用了stopSelf(),否则Service一直运行。
    2. 程序通过Service对外开放某些操作。通过bindService()方式与Service调用,长期连接和交互,Service生命周期和其绑定的组件相关。

    Service Lifecycle

    public class MyService extends Service {
    
        @Override
        public void onCreate() {
            super.onCreate();
        }
    
        @Override
        public int onStartCommand(Intent intent, int flags, int startId) {
            return startCommandReturnId;
        }
    
        @Override
        public void onDestroy() {
            super.onDestroy();
        }
    
        @Nullable
        @Override
        public IBinder onBind(Intent intent) {
            return null;
        }
    }
    

    要解释这个首先要知道Service的实现,需要实现抽象方法onBind,以及重写onStartCommand,这2个方法会在下文介绍到。

    通过上面的介绍可以知道,Service有3种启动方式:

    1. startService()
    2. bindService()
    3. 同时调用

    这几种方式启动的Service生命周期略微不同。

    startService方式

    startService()只要一个Intent参数,指定要开启的Service即可

    Intent intent = new Intent(MainActivity.this, MyService.class);
    
    1. 当调用Service的startService()后,

      • Service首次启动,则先调用onCreate(),在调用onStartCommand()
      • Service已经启动,则直接调用onStartCommand()
    2. 当调用stopSelf()或者stopService()后,会执行onDestroy(),代表Service生命周期结束。

    3. startService方式启动Service不会调用到onBind()。 startService可以多次调用,每次调用都会执行onStartCommand()。 不管调用多少次startService,只需要调用一次stopService就结束。 如果startService后没有调用stopSelf或者stopService,则Service一直存活并运行在后台。

    4. onStartCommand的返回值一共有3种

      • START_STICKY = 1:service所在进程被kill之后,系统会保留service状态为开始状态。系统尝试重启service,当服务被再次启动,传递过来的intent可能为null,需要注意。
      • START_NOT_STICKY = 2:service所在进程被kill之后,系统不再重启服务
      • START_REDELIVER_INTENT = 3:系统自动重启service,并传递之前的intent

      默认返回START_STICKY;

    bindService方式

    通过bindService绑定Service相对startService方式要复杂一点。 由于bindService是异步执行的,所以需要额外构建一个ServiceConnection对象用与接收bindService的状态,同时还要指定bindService的类型。

    //1\. 定义用于通信的对象,在Service的onBind()中返回的对象。
    public class MyBind extends Binder {
            public int mProcessId;
     }
    
    //2\. 定义用于接收状体的ServiceConnection
    mServiceConnection = new ServiceConnection() {
                @Override
                public void onServiceConnected(ComponentName name, IBinder service) {
                    //和服务绑定成功后,服务会回调该方法
                    //服务异常中断后重启,也会重新调用改方法
                    MyService.MyBind myBinder = (MyService.MyBind) service;
                }
    
                @Override
                public void onNullBinding(ComponentName name) {
                    //Service的onBind()返回null时将会调用这个方法,并不会调用onServiceConnected()
                }
    
                @Override
                public void onServiceDisconnected(ComponentName name) {
                    // 当服务异常终止时会调用。
                    // 注意,unbindService时不会调用
                }
            };
    
    //3\. 在需要的地方绑定到Service
    bindService(intent, mServiceConnection, BIND_AUTO_CREATE);
    

    bindService()也可以调用多次,与startService()不同,当发起对象与Service已经成功绑定后,不会多次返回ServiceConnection中的回调方法。

    通过bindService方式与Service进行绑定后,当没有对象与Service绑定后,Service生命周期结束,这个过程包括绑定对象被销毁,或者主动掉调用unbindService()

    startService和bindService同时开启

    当同时调用startService和bindService后,需要分别调用stopService和unbindService,Service才会走onDestroy()

    一个Service必须要在既没有和任何Activity关联又处理停止状态的时候才会被销毁。

    IntentService

    通过上面的介绍我们知道,通过StartService形式开启Service时,如果不主动调用stopService,Service将在后台一直运行。同时如果我们在Service中执行耗时操作还是引起ANR异常,为了解决这2个问题,IntentService出现了。 当我们需要执行某些一次性、异步的操作时,IntentService能很好的满足这个场景。

    IntentService相比于普通的Service,在使用时将不再需要实现onStartCommand(),同时需要实现onHandleIntent()。 真正需要我们处理的逻辑就在onHandleIntent()实现,IntentService会内部自动调用stopSelf()关闭自己。

    至于防止ANR异常,具体的实现方式其实还是挺简单,就是在内部新建了子线程,并在子线程中内部的Looper来分发事件,具体代码就不贴了。

    下一篇Android Service详解(二)将介绍通过Service实现IPC通信
    【附】相关架构及资料
    image

    资料领取

    点赞+加群免费获取 Android IOC架构设计

    加群领取获取往期Android高级架构资料、源码、笔记、视频。高级UI、性能优化、架构师课程、NDK、混合式开发(ReactNative+Weex)微信小程序、Flutter全方面的Android进阶实践技术,群内还有技术大牛一起讨论交流解决问题。

    相关文章

      网友评论

        本文标题:Android Service详解(一)

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