Service原理详解

本文详细介绍了Android Service的工作原理,包括Service的启动、绑定、生命周期和通信方式。重点解析了startService()和bindService()的流程,以及它们的区别和结合使用场景。同时,探讨了Service生命周期中的关键方法,如onCreate()、onStartCommand()、onBind()、onUnbind()和onDestroy()。此外,还讲解了Service的启动模式、ServiceConnection的onServiceConnected()、Service的桥接模式和组合模式。最后,文章提供了面试中常见的Service相关问题及其解答。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

转载请注明链接: https://blog.youkuaiyun.com/feather_wch/article/details/50300853

详解Service的原理有帮助,请点个赞!

Service原理详解

版本:2018/9/1-1(18:00)


基础(6)

1、Service是什么?

  1. 一种服务型组件,用于在后台执行一系列计算任务(处理网络事务、播放音乐、文件读写、或者与ContentProvider交互)。
  2. 没有界面的组件。
  3. Service具有两种状态:启动状态绑定状态
  4. 本地Service运行在主线程(UI线程)中,因此不能进行耗时操作,需要创建子线程才可以。(BoradcastReceiver也是如此)

2、Service的两种状态

  1. 启动状态: 进行后台任务,Service本身运行在主线程,因此耗时操作需要在新线程中处理
  2. 绑定状态: 内部同样可以进行后台运算,但是此时外界可以很方便与Service通信

3、Service如何停止?

  1. 如果是启动状态:stopService()或者Service的stopSelf()来停止。
  2. 如果是绑定状态: unBindService()后,Service停止
  3. 如果是启动&绑定状态:需要执行unBindeService()和stopService()或者Service的stopSelf(),才能真正停止。

4、Service的分类

  1. 本地服务:一般的Service
  2. 远程服务: 通过android:process属性,运行在独立进程中。

5、本地服务是什么?

  1. 该类服务依赖在主进程上而不是独立的进程,一定程度上节约资源。
  2. 本地服务因为在同一进程内,不需要IPC和AIDL进行交互。bindService也方便很多。
  3. 缺点:限制性大,主进程被杀死后,服务便会终止
  4. 应用场景:需要依附某个进程的服务,比如音乐播放。

6、远程服务是什么?

  1. 该服务是独立的进程,进程名为所在包名 + android:process指定的字符串
  2. 定义方式:用android:process=".service"
  3. 特点: 主进程被杀死后,该服务依然存在,不受其他进城影响,能为多个进程提供服务,具有灵活性。
  4. 会消耗更多资源,并且使用AIDL进行IPC比较麻烦,一般用于系统Service。
  5. 从Android 5.0开始,APP结束后会关闭相关进程树,因此相关的服务也会被杀死。

生命周期(4)

1、Service的生命周期
Service的生命周期

  1. 仅仅是startService:onCreate()->onStartCommand()->onDestory()
  2. 仅仅是bindService:onCreate()->onBind()->onUnbind()->onDestory()
  3. 同时使用startService开启服务与bindService绑定服务:onCreate()->onStartCommand()->onBind()->onUnbind()->onDestory()

2、Service生命周期的

生命周期 解释 注意点
onCreate() 第一次启动时调用 适合只执行一次的操作
onStartCommand() 执行startService会调用 可能会多次调用,bindService不会调用
onBind() 执行bindSevice时调用 多次bindService不会导致调用多次
onUnbind() 执行unBindService()时调用 返回值会决定,再次bindService()会执行onBind()还是onRebind()
onDestory() 销毁 做一些清理工作

3、onStartCommand()的返回值有什么用?

  1. 返回START_STICKY时,如果Service因为内存不足,被系统杀掉后。如果有了多余内存,会尝试重新创建这个Service。
  2. 并且会调用onStartCommand(),其中的Intent将会为null。为了那些循环的音乐播放器,天气预报之类的服务。
// Service.java
public @StartResult int onStartCommand(Intent intent, @StartArgFlags int flags, int startId) {
    onStart(intent, startId);
    return mStartCompatibility ? START_STICKY_COMPATIBILITY : START_STICKY;
}

4、Service的unbindService生命周期
Service的unbindService生命周期

  1. 客户端执行unBindService()后,回调onUnBind()方法,如果返回true,Service销毁。
  2. onUnBind()如果返回false,判断是否调用了stopSelf或者stopService,调用则继续消息Service
  3. 没有调用,则不会销毁。客户端再次调用bindService(), 会执行onRebind()
  4. 销毁后,调用bindService()会执行onBind()进行绑定。

通信(4)

1、Activity与Service间的通信方式

  1. Activity调用Service的方法:Activity通过调用bindService,在ServiceConnection的onServiceConnected可以获取到Service的对象实例,然后就可以访问Service中的方法.
  2. Service去主动通知Activity的方法:可以通过回调来实现—在Activity的ServicConnection的onServiceConnected中去给Service设置实现的接口,该接口会在Service中被调用。
  3. 通过广播
  4. 通过EventBus

2、onBind()和onServiceConnected()实现通信

1-自定义Service,onBind()返回自定义的Binder

class MyService extends Service {
    public IBinder onBind(Intent intent) {
        return new MyBinder();
    }
    class MyBinder extends Binder{
        MyService getService() {
            return MyService.this;
        }
    }
    public void method(){}
}

2-onServiceConnected()去接收Service

class MyServiceConnection implements ServiceConnection {
    public void onServiceConnected(ComponentName name, IBinder service) {
        // 1、获取Sevice
        MyService myService = ((MyService.MyBinder)service).getService();
        // 2、调用其方法
        myService.method();
    }
    public void onServiceDisconnected(ComponentName name) {
    }
}

3、ServiceConnection的onServiceDisconnected什么时候会被调用?

  1. 和Service连接意外中断。
  2. 如因为内存不足,Service被意外释放掉。

4、用户解绑和终止Service会调用onServiceDisconnected吗?

不会

启动模式(21)

1、Service的启动方式有什么区别

  1. startService:Service与组件的生命周期无关,即使组件退出,Service依然存在。耗电,占内存。
  2. bindService:调用者退出后,Service也会退出。

2、startService

  1. Service无论调用多少次startServiceonCreate只会调用一次,onStartCommand会调用相应次数。
  2. Service无论调用多少次startService,只存在一个Service实例
  3. 结束Service只需要调用一次stopService或者stopSelf
  4. Activity的退出并不会导致Service的退出—除非在onDestory里面调用stopService,但是退出APP会导致Service的退出!
  5. 系统资源不足的时候,服务可能会被Kill

3、bindService

  1. Service通过bindService启动,无论调用多少次,onCreate只会调用一次,且onStartCommand不会被调用。
  2. 如果调用Service的组件退出,如Activity,Service就会被停止。
  3. bindService开启的Service的通信比较方便,本地服务不需要AIDL和IPC,但是远程服务是需要AIDL和IPC的。

4、startService且同时bindService

  1. onCreate之调用一次。
  2. startService调用几次,onStartCommand会调用相同次数。
  3. bindService不会调用onStartCommand
  4. 调用unBindService不会停止Service,必须调用stopService和Service自身的stopSelf来停止。
  5. 如果想停止这种Service,unBindeServicestopService都需要调用,缺一不可。

5、同时开启和绑定有什么作用?

  1. 能让Service一直处于后台运行的状态,即使组件已经退出。
  2. 同时通过bindService能方便地与Service通信
  3. 相比于广播的方式,性能更高。

6、Service的注意点

  1. 手机发生旋转时,Activity的重新创建,会导致之前bindService建立的连接断开,Service会因为COntext的销毁而自动停止。

startService流程

7、Service的启动方法

Intent intent = new Intent(this, MyService.class);
startService(intent);
  1. Service有启动状态绑定状态
  2. 两个状态可以共存,Service可以既处于启动状态又处于绑定状态

8、Service的startService过程流程图和要点?

graph TD;
    1(1.startService);
    2(2.mBase.startService);
    3(3.startServiceCommon);
    4(4.ActivityManager.getService.startService);
    5(5.mServices.startServiceLocked);
    6(6.bringUpServiceLocked);
    7(7.realStartServiceLocked);
    8(8.app.thread.scheduleCreateService);
    9(9.sendServiceArgsLocked);
    10(10.handleMessage);
    11(11.handleCreateService);
    16(16.app.thread.scheduleServiceArgs);
    17(17.handleMessage);
    18(18.handleServiceArgs);
    19(19.onStartCommand);
    1-->2;
    2-->3;
    3-->4;
    4-->5;
    5-->6;
    6-->7;
    7-->8;
    7-->9;
    8-->10;
    10-->11;
    9-->16;
    16-->17;
    17-->18;
    18-->19;
  1. startService(ContextWrapper.java):Activity层层继承自ContextWrapper;内部交由ContextImplstartService();典型的桥接模式
  2. mBase.startService(ContextImpl.java): 交给ContextImpl执行。
  3. startServiceCommon(ContextImpl.java): 通过ActivityManagerService启动服务;IPC
  4. startService(ActivityManagerService.java):通过ActiveServices进行后续工作—调用mServices.startServiceLocked
  5. startServiceLocked(ActiveServices.java): bringUpServiceLocked
  6. bringUpServiceLocked(ActiveServices.java): realStartServiceLocked
  7. realStartServiceLocked(ActiveServices.java): 1、app.thread.scheduleCreateService 2、sendServiceArgsLocked
  8. app.thread.scheduleCreateService(ActivityThread.java):1. 创建Service 2. 发送消息CREATE_SERVICE给Handler H
  9. sendServiceArgsLocked(): 用Service的其他方法(如onStartCommand)-IPC通信
  10. handleMessage(ActivityThread.java): 处理消息
  11. handleCreateService(ActivityThread.java): 处理第12、13、14、15 四步的工作, 进行Service的创建工作
  12. 16.app.thread.scheduleServiceArgs: IPC让ActivityThread只去执行其他的生命周期回调。发送消息给Handler H
  13. 17.handleMessage: 调用handleServiceArgs
  14. 18.handleServiceArgs: 执行其他的生命周期,如onStartCommand
  15. 19.onStartCommand: Service的回调方法
graph TD;
    11(11.handleCreateService);
    12(12.cl.loadClass);
    13(13.makeApplication);
    14(14.service.attach);
    15(15.service.onCreate);
    11-->12;
    11-->13;
    11-->14;
    11-->15;
  1. handleCreateService(ActivityThread.java): 处理第12、13、14、15 四步的工作
  2. cl.loadClass().newInstance(): 类加载器创建Service实例。
  3. packageInfo.makeApplication: 用LoadedApk创建Application实例
  4. service.attach: 创建ContextImpl建立Context和Service的联系。
  5. service.onCreate(): Service的onCreate(), 并且将Service对象存储到ActivityThread中的一个列表中

9、ActiveServices是什么?

  1. 辅助ActivityManagerService进行Service管理
  2. 包括:启动、绑定、停止等

10、ServiceRecord是什么?

  1. 描述一个Service记录,贯穿整个启动过程

11、ContextWrapper是什么?

  1. ContextWrapper是Context实现类ContextImpl的包装类
  2. Activity、Service等都是直接或者间接继承自ContextWrapper

12、ContextWrapper为什么是典型桥接模式?

见下面的知识扩展部分

13、桥接模式和代理模式的区别?

见下面的知识扩展部分

源码解析

14、Service的启动过程源码详细分析

   /**
     * ======================================
     * 1. Activty层层继承自ContextWrapper
     * 2. Activty的startService()方法来自于ContextWrapper
     * 3. ContextWrapper最终由mBase(ContextImpl)完成-典型桥接
     * ======================================
     */
    //ContextWrapper.java
    public ComponentName startService(Intent service) {
        //1. mBase就是Context的实现ContextImpl对象(也就是Activity创建时关联的对象)
        return mBase.startService(service);
    }

    //ContextImpl.java:直接调用startServiceCommon
    public ComponentName startService(Intent service) {
        warnIfCallingFromSystemProcess();
        return startServiceCommon(service, false, mUser);
    }

    //ContextImpl.java
    private ComponentName startServiceCommon(Intent service, boolean requireForeground, UserHandle user) {
        ......
        //1. 让`ActivityManagerService`启动一个Service服务
        ComponentName cn = ActivityManager.getService().startService(
                mMainThread.getApplicationThread(), service, ...省略...);
        ......
    }

    //ActivityManagerService.java
    public ComponentName startService(IApplicationThread caller, Intent service, ...) {
        /**====================================
         * 1. 通过mService(ActiveServices)完成后续过程
         * 2. ActiveServices是辅助AMS进行Service管理的类
         *     -包括:启动、绑定、停止
         * 3. `startServiceLocked`方法尾部会调用`startServiceInnerLocked`
         *=====================================*/
        res = mServices.startServiceLocked(caller, service, ...,userId);
    }

    //ActiveServices.java
    ComponentName startServiceInnerLocked(...,ServiceRecord r) {
        ......
        /**=========================================
         * ServiceRecord描述的是一个Service记录(贯穿整个启动过程)
         * 1. startServiceInnerLocked并没有完成具体启动工作,而是把后续任务交给了bringUpServiceLocked
         * 2. bringUpServiceLocked内部调用`realStartServiceLocked`
         * 3. realStartServiceLocked真正启动了Service
         *==========================================*/
        String error = bringUpServiceLocked(r, service.getFlags(), callerFg, false, false);
        ......
        return r.name;
    }

    //ActiveServices.java
    private final void realStartServiceLocked(ServiceRecord r, ProcessRecord app, boolean execInFg) {
        ......
        /**========================================================
         * 创建了Service对象,并且调用了onCreate()方法-IPC通信
         * 1. app.thread对象是IApplicationThread类型(Binder)
         * 2. 具体实现是ActivityThread(继承了ApplicationThreadNative)
         *========================================================*/
        app.thread.scheduleCreateService(r, r.serviceInfo, ......);
        ......
        //2. 用于调用Service的其他方法(如onStartCommand)-IPC通信
        sendServiceArgsLocked(r, execInFg, true);
        ......
    }

    //ActivityThread.java的内部类:ApplicationThread
    public final void scheduleCreateService(IBinder token, ...,int processState) {
        updateProcessState(processState, false);
        CreateServiceData s = new CreateServiceData();
        s.token = token;
        s.info = info;
        s.compatInfo = compatInfo;
        /**========================================
         *  1. 发送消息给Handler H处理
         *  2. H会接受消息,并且调用ActivityThread的handleCreateService
         *========================================*/
        sendMessage(H.CREATE_SERVICE, s);
    }

    /**====================================
     * 完成Service最终启动工作
     * //ActivityThread.java
     *=====================================*/
    private void handleCreateService(CreateServiceData data) {
        //1. 通过类加载器创建Service实例
        Service service = null;
        java.lang.ClassLoader cl = packageInfo.getClassLoader();
        service = (Service) cl.loadClass(data.info.name).newInstance();
        //2. 创建Application对象并调用其onCreate方法(Application是唯一的不会重复创建)
        Application app = packageInfo.makeApplication(false, mInstrumentation);
        //3. 创建ContextImpl对象并通过Service的attach方法建立两者关系(类似Activity的过程)
        ContextImpl context = ContextImpl.createAppContext(this, packageInfo);
        context.setOuterContext(service);
        service.attach(context, this, data.info.name, data.token, app, ActivityManager.getService());
        //4. 调用service的onCreate方法,并且将Service对象存储到ActivityThread中的一个列表中
        service.onCreate();
        mServices.put(data.token, service);
        ......
    }

    /**=============================================================
     * ActivityThread中还会通过handleServiceArgs方法调用Service的onStartCommand
     *=============================================================*/
    private void handleServiceArgs(ServiceArgsData data) {
        Service s = mServices.get(data.token);
        ......
        //1. Service的onStartCommand方法
        res = s.onStartCommand(data.args, data.flags, data.sta
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

猎羽

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值