面试:Service及生命周期相关问题

发布于:2022-11-09 ⋅ 阅读:(6) ⋅ 点赞:(0) ⋅ 评论:(0)

Q1:Service的两种启动方式:

1.startService

2.bindService(有回调可以和activity进行通信)

注意:在Android 5.0之后google出于安全的角度禁止了隐式声明Intent来启动Service,也禁止使用Intent filter,否则就会抛出异常
 

Q2:启动与停止Service两种方式

第一种:通过startService()与stopService()启动和停止服务,Service与启动它的Activity无法进行通信和数据交换
第二种:通过bindService()与unbindService()启动和停止服务。在启动时,通过bindService(Intent, ServiceConnection, int)启动服务,unbindService(ServiceConnection) 停止服务,ServiceConnection参数为交互数据的对象
 

Q3:Activity和Service的交互方式主要有以下几种?

  • 通过广播进行交互
  • bindService()启动service,进行交互
  • 通过共享文件
  • Messenger
  • AIDL

Q4:onStartCommand的几种返回值有什么效果?

在service的onStartCommand()方法中有个返回值,返回值一般分为下面三种,表示当service异常销毁的时候,service后续启动情况。

  • START_NOT_STICKY: service如果被干掉,不会再自动重启。
  • START_STICKY:service如果被干掉,会自动重启,但是onStartCommand回调方法的Intent参数为null。如果你的Service可以在任意时刻运行或结束都没什么问题,而且不需要intent信息,那么就可以在onStartCommand方法中返回START_STICKY,比如一个用来播放背景音乐功能的Service就适合返回该值。
  • START_REDELIVER_INTENT:service如果被干掉,会自动重启,Android系统会再次将Service在被杀掉之前最后一次传入onStartCommand方法中的Intent再次保留下来并再次传入到重新创建后的Service的onStartCommand方法中,这样我们就能读取到intent参数。如果我们的Service需要依赖具体的Intent才能运行(需要从Intent中读取相关数据信息等),并且在强制销毁后有必要重新创建运行,那么这样的Service就适合返回START_REDELIVER_INTENT。

Q5:service保活有哪些方法?

  1. onStartCommand方法返回START_STICKY或者START_REDELIVER_INTENT;
  2. 提高Service的优先级,在AndroidManifest.xml文件中对于intent-filter可以通过android:priority = "1000"这个属性设置最高优先级,1000是最高值,如果数字越小则优先级越低,同时适用于广播。
  3. 在Service即将销毁的时候重新启动;或者注册一个广播,然后在service的onDestroy中发送广播,在广播中实现拉起;
  4. 提升service进程优先级,使用前台服务;
  5. 通过系统的一些广播,比如:手机重启、界面唤醒、应用状态改变等等监听并捕获到,然后判断我们的Service是否还存活
  6. 开启一个守护进程,实时监听;
  7. AlarmManager + JobScheduler;
  8. 双进程守护,AIDL方式单进程、双进程方式保活Service;
  9. 白名单:跳转到系统白名单界面让用户自己添加app进入白名单;
  10. 安装到system/app,使其成为系统应用。

Q6:service生命周期

1、startService启动服务:

startService()执行的生命周期:onCreate() —> onStartCommand()

1)点击启动Service服务startService()
单次点击:onCreate() —> onStartCommand()
多次点击:onCreate() —> onStartCommand() —> onStartCommand()—> onStartCommand()... ...

注意:多次启动服务onCreate()只会执行一次,onStartCommand()会执行多次。
2)点击停止Service服务stopService()
onDestroy()

2、bindService绑定服务:

bindService执行的生命周期:onCreate() —> onBind()—> onUnbind() —> onDestroy()

1)点击绑定Service服务bindService()
onCreate() —> onBind()
2)点击解绑Service服务unbindService()
onUnbind() —> onDestroy()

bindService 如果被不断的重复调用,会有问题吗? - 旺仔牛轧糖 - 博客园

如果调用bindService()方法前服务已经被绑定,多次版调用bindService()方法并不会导致多次创建服务及绑定(也就是说onCreate()和onBind()方法并不会被多次调用)。如果调用者希望与正在绑定的权服务解除绑定,可以调用unbindService()方法,调用该方法也会导致系统调用服务的onUnbind()-->onDestroy()方法。

采用Context.bindService()方法启动服务,在服务百未被创建时,系统会先调用服务的onCreate()方法,度接着调用onBind()方法。这个时候调用者和服务绑定在一起,调用者退出了,系统就会先问调用服务的onUnbind()方法,接着调用答onDestroy()方法。

3​​​​​​​、先启动后绑定服务

先点击startService然后点击bindService的生命周期:

onCreate() —> onStartCommand()—> onBind()—> onUnbind()—> onDestroy()

1)点击启动,然后点击绑定Service服务:startService()—> bindService()
onCreate() —> onStartCommand() —> onBind()
2)先点击停止,然后点击解绑Service服务:stopService() —> unbindService()
onUnbind() —> onDestroy()

4、​​​​​​​先绑定后启动服务

先bindService后startService的生命周期:

onCreate() —> onBind()—> onStartCommand()—> onUnbind()—> onDestroy()

1)启动绑定Service服务bindService()—> startService()
onCreate() —> onBind() —> onStartCommand()
2)先点击解绑,然后点击停止Service服务:unbindService() —> stopService()
onUnbind() —> onDestroy()

5、​​​​​​​先解绑后绑定服务

先解绑后绑定Service服务unbindService() —> bindService()
onUnbind(ture) —> onRebind()

引申问题Q7:多次bindService但是被绑定service的onBind只走一次的解决办法

多次bindService但是被绑定service的onBind只走一次的解决办法_牛客博客

多组件绑定同一个service,出现问题:只有第一个服务绑定的时候会调用onBind()方法,并且service返回的都是同一个service:

原因:要指定多组件绑定service,输入的时候bindservice会认为intent是一样的,就会默认使用第一次调用的onbind传回的IBinder,这样的话,会发现服务绑定的内存地址也是同一个。其实就是它一直用的第一个服务绑定的地址。

解决办法:给intent指定一个type,区分多次intent的类型即可:

 //main button点击事件 :绑定服务1
 public void bindClick(View view){
        Log.v("chendandan","bindClick()");
        if(myConn==null){
             myConn=new MyConn();
        }
        Intent intent=new Intent(MainActivity.this,MyService.class);
         //指定type
        intent.setType("main");
        bindService(intent,myConn,BIND_AUTO_CREATE);
    }
//child buttion点击事件:绑定服务2
public void bindClick(View view){
        Log.v("chendandan","bindClick()");
        if(myConn==null){
            myConn=new MyConn();
        }
        Intent intent=new Intent(MainActivity2.this,MyService.class);
        //指定type
        intent.setType("child");
        bindService(intent,myConn,BIND_AUTO_CREATE);
}

运行结果:

 

引申问题Q8:多次bindService但是被绑定service的onBind只走一次的原因

情况一: App A绑定App B的service,App A多次调用bindService(),而不调用unbindService(),此时App B的service的onBind()只执行一次

情况二: App A,App C绑定App B的service,App A和App C各调用一次或多次bindService(),而不调用unbindService(),此时App B的service的onBind()只执行一次

上面提到的两种情况有2个共同点:

(1)每次调用bindService()时,绑定的服务是一样的;
(2)没有调用unbindService()
Android中bindService的细节之三:多次调用bindService(),为什么onBind()只执行一次?_weixin_41205419的博客-CSDN博客_多次调用bindservice​​​​​​​