简述
Service作为Android的四大组件之一,使用频率仅次于Activity,使用时需在manifest进行注册。
由于service运行在主线程,所以不能进行耗时操作需另起线程。
API
Android 5.0 后service禁止隐式启动,需指明启动者
启动方式
有两种:
- start(无交互,默默的后台工作)
- bind(有交互可用于进程间通讯IPC)
启动方式的不同会有不同的生命周期。
startService()启动的Service和启动者的生命周期无关,必须要显示调用stopService/stopSelf方法,才能停止该Service;
bindService()启动的Service和启动者的生命周期有关,当启动者销毁时,会自动解绑该Service。
同一service被多次使用的场景:
-
startService - startService
第一次的startService会有onCreate()>onStartCommand()实例创建成功开始工作
第二次的startService并不会创建新的实例,而是使用之前的实例并执行onStartCommand()
当调用stopService()或任务执行完毕实例自己stopSelf()时onDestroy()执行,多次调用无效实例只有一个。 -
startService - bindService
startService时实例创建onCreate()>onStartCommand()
bindService时由于已存在实例,onBind()执行
stopService()、stopSelf()由于实例还有引用所以不会触发任何方法
unbindService()时触发onUnbind()此时实例没有引用紧接着onDestroy()
bindService- startService 顺序反过来即可 -
bindService- bindService(绑定者不同情况,绑定者相同不会触发任何)
第一次的bindService会有onCreate()>onBind()执行,此时实例创建
第二次的bindService并没有触发onBind()(对于service而言已经绑过了,至于几次并不影响),但会返回IBinder给绑定者即onServiceConnected
若绑定者unbindService此时service没有引用则调用onUnbind()>onDestroy(),若还有其他引用service不会被销毁
若一绑定者多次调用unbindService则 java.lang.IllegalArgumentException: Service not registered:
若调用者结束前没有调用unbindService,则会造成内存泄漏android.app.ServiceConnectionLeaked,警告过后系统会unbindService。
onBind 返回 null 时不会回调 onServiceConnected
onServiceDisconnected异常断开才会回调
多进程
Android的四大组件都可以设置多进程,在manifest中设置android:process属性。
目的
- 进程为资源分配的最小单元,一个应用多个进程则可以获取系统更多的资源。
- 功能分离,界面交互、消息推送、APP心跳等可在不同进程中执行,一个进程杀掉后不会影响其他功能
实现
多进程分为两种:私有进程和全局进程。
私有进程
属性设置以“:”开头表示开启的新进程为当前进程所私有,不能够跨进程使用。
全局进程
属性设置以小写字母开头的进程为全局进程,可以被多个应用共用,详细内容会有进程间通讯篇。
缺点
-
每开启一个进程的时候,Application就会执行一遍onCreate(),一般会在里面做一些初始化操作。多次执行必定会导致没有必要的各种浪费,所以需要在初始化的时候判断当前进程。(我的第一篇博文就是这个Android项目之Application,当时只知道这么写却没想这么深)
-
数据共享问题
多进程之间数据无法共享,需要进程间通讯。 -
SQLite容易被锁
多进程操作数据库,可能会发生死锁。
保活
保活有两种方式:提高进程的优先级、多进程之间互相拉活
优先级
进程按优先级分为:前台进程、可见进程、服务进程、后台进程、空进程
- 前台进程,当前用户操作所需要的进程
1、用户正在交互的Activity(Activity执行了onResume方法)
2、Service绑定到正在交互的Activity
3、Service设置为前台(Service调用startForeground()方法)
4、正在执行某些生命周期回调的Service,onCreate()、onStart()、onDestroy()
5、正在执行onReceive()的BroadcastReceiver
这种进程基本不会被回收,只有当内存不足以支持前台进程同时运行的时候,系统才会回收它们,主要关注前三个。
-
可见进程,没有与用户交互所必须的组件,但是在屏幕上仍然可见其内容的进程
1、调用了onPause()方法但仍对用户可见的Activity
2、绑定到上面这种Activity的Service -
服务进程
1、使用startService()启动的Service且不属于上面两种类别的进程
虽然这个进程与用户交互没有直接关系,但是一般会在后台执行一些耗时操作,所以,只有当内存不足以维持所有前台进程和可见进程同时运行,系统才会回收这个类别的进程。
-
后台进程,
1、对用户不可见Activity进程,已调用了onStop()方法的Activity -
空进程,不包含任何活动应用组件的进程,保留这种进程唯一目的是作为缓存,缩短引用组件下次启动时间。通常系统会最优先回收这类进程。
通过提升进程的优先级,可以减少被系统回收的概率。方案有:
- 一像素Activity
- 前台service
- 播放空音频(耗电)
拉活
多个进程之间互相监听,当发现其中一个进程被kill后其他进程将其再次启动(用户手动清除的,APP进程组全部被清,所以拉活仅限系统回收和多APP之间)。
方案(目前可行):
- JobScheduler
网友评论