你是否真正理解了service的start和bind方式下的生命周期

对于四大组件之一Service,我们知道它是一般用于后台运行的,有两种方式开启Service,即Start方式和bind方式。
小编我在最近的面试中,就被面试官给考住了,把我给绕晕了,原因就是没有真正亲自验证一下这两种方式下Service的生命周期,这不,亡羊补牢来啦,走起!

1. Service是什么?

Service是android中实现后台运行的解决方案,既然在后台运行,一般不需要和用户进行交互,完成一些后台比较耗时的逻辑处理。当然,千万不要被迷惑,郭神在第一行代码中也说了,虽说叫后台服务,但是实际上也是运行在主线程中,那么你可有一些UI处理的话,也是可以的,比如弹出个Toast!但是更要注意的是,不要直接在这个服务中直接写比较耗时的操作,比如网络下载,文件读写,如果你不信,出现ANR你就信了。

有人就会问了,既然是服务,那为啥不是直接让开发者能够使用,完成一些耗时操作呢,还要自己进行多线程编程,嘿嘿,我暂时也不知道,谷歌为什么这么设计?

提到了多线程编程,那么在Service中怎么实现网络下载等耗时操作呢?这里只简单提一下,可以自己开线程,也可以使用AsycTask,还可以用IntentService,暂时只想到这些。

好了,有点扯远了,回归本题,只要来说说Service两种使用方式的生命周期。

2. Service启动方式

Start方式:

特点:

(1)一般用于Activity中不需要和Service交互,这也是和bind方式的主要区别

(2)通过startService方法开启后就和Activity的关系不大了,Activity的生命周期不再影响Service了,但是Activity有权关掉Service,通过调用stopService来暂停服务,或者在Service中自己调用StopSelf()来停止服务

(3)这种方式下的生命周期:

onCreate-------------第一次开启时调用

onStartCommand-------每次启动都会调用

onDestroy------------服务停止时调用

(4)onStartCommand方法返回值是int类型,有以下四种类型:

START_STICKY_COMPATIBILITY:START_STICKY的兼容版本,Service被kill后不保证onStartCommand会再执行

START_STICKY:Service开启后如果被kill后,会保留开启状态,但是不保存intent。系统会重启serveice,重新回调onStartCommand方法,如果没有Start命令,会传递一个为null的intent,所以需要对intent作非空判断。

START_NOT_STICKY:Service被kill后,不会保留开启状态,如果没有其他组件来开启,系统不会重启该Service。

START_REDELIVER_INTENT:从名字上可以看出,Service被kill掉之后,系统会重新传递上一次传过来intent,重启Service;该intent会保留到调用stopself。该参数下不传递值为null的intent。

(5)默认的返回值

依赖于目标SDK版本,看下源码

private boolean mStartCompatibility = false;//初始为false

public final void attach(
            ...
        mStartCompatibility = getApplicationInfo().targetSdkVersion
                < Build.VERSION_CODES.ECLAIR;//目前SDK版本小5是为true,大于等于5时为false
    }

//从父类方法中看出,为false(SDK版本>=5)时,返回值为START_STICKY;
//为true(SDK版本<5)时,返回值为START_STICKY_COMPATIBILITY
public @StartResult int onStartCommand(Intent intent, @StartArgFlags int flags, int startId) {
    onStart(intent, startId);
    return mStartCompatibility ? START_STICKY_COMPATIBILITY : START_STICKY;
}

现在一般目标SDK都会大于5,所以默认返回值为START_STICKY,服务被kill掉后,系统会重新启动服务

bind方式:

特点:

一、一般用于和组件间进行通讯,如Activity要和Service之间通讯,则需要使用bind方式,在Service中需要创建一个binder,然后通过onBind方法返回给Activity,在Activity中创建一个ServiceConnection用于接收这个Binder,以上就是Service绑定方式的主要使用步骤。

二、bind方式开启的Service,与组件的生命周期相关,如,当Activity销毁时,Service也就结束了。但是,Activity销毁后,需要手动在onDestroy中unbind解绑Service,否则会出现内存泄漏,所以如果是绑定方式开启的服务,一定要记得解绑定。

MainActivity has leaked ServiceConnection com.ralf.www.servicetest.MainActivity$1@861526a that was originally bound here
   android.app.ServiceConnectionLeaked: Activity com.ralf.www.servicetest.MainActivity has leaked ServiceConnection com.ralf.www.servicetest.MainActivity$1@861526a that was originally bound here
      at android.app.LoadedApk$ServiceDispatcher.<init>(LoadedApk.java:1092)
      at android.app.LoadedApk.getServiceDispatcher(LoadedApk.java:986)
      at android.app.ContextImpl.bindServiceCommon(ContextImpl.java:1303)
      at android.app.ContextImpl.bindService(ContextImpl.java:1286)

三、bind方式下的生命周期:假设一个Activity A,一个MyService

(1)A绑定后MyService后,会走onCreate----onBind,如果绑定再次绑定不会有任何操作,因为已经绑定了;如果A解绑定,会走MyService的onDestroy,

(2)A绑定MyService后,又调用start方式开启

onCreate----onBind----onStartCommand

此时如果解绑定,服务仍存在,若要停止服务,需要解绑定一次,stopService一次,没有先后顺序

3.与Activity的关系

首先,来回顾一下Activity的生命周期(这里测试使用的是nexus 5X,有虚拟按键),两个Activity A 和 B和一个MyService,A上有按钮可以开启B

(1)打开A,onCreate---onStart---onResume

(2)按back键,退出A到桌面:onPause----onStop---onDestroy

(3)接着如果重新打开A,onRestart----onStart---onResume

(4)如果按home(虚拟键的圆圈)键或者任务管理(虚拟键的方块),onPause---onStop

(5)息屏:onPause----onStop

(6)亮屏解锁:onRestart----onStart---onResume

(7)跳转活动B:onPause----onCreate(B)---onStart(B)---onResume(B)---onStop---onDestroy

(8)back返回A:onPause(B)----onCreate(A)---onStart(A)---onResume(A)---onStop(B)---onDestroy(B)

好,下面来看下在这两个活动下Service的生命周期

(1)A绑定Service,然后跳转B,B在绑定Service:onCreate----onBind---onDestroy---onCreate----onBind

(2)A绑定Service,然后跳转B,B start Service:onCreate----onBind---onDestroy---onCreate----onStarCommand

(3)A start Service,然后跳转B,B bind Service:onCreate----onStarCommand---onBind(B)

(4)A start Service,然后跳转B,B bind Service,back返回A,A bind Service(不会再走onBind):onCreate----onStarCommand---onBind(B)

(5)A start Service,然后跳转B,B start Service:onCreate(A)----onStarCommand(A)---onStarCommand(B)

这里给出几种情况,并没有给出分析。但是总结一下,start后,Service一直存在,如果想要停止,可以在任意一个组件中调用一次StopService即可。start前提下开启的Service,初次bind会调用onBind,之后只要Service仍存在,后面再被bind,不会再走onBind。

4. IntentService

前面提到要想在Service中实现多线程编程,那么可以自己开启线程,但是有时可能忘记线程开启,而且Service也要自己停止。所以出现了一个IntentService,帮我们封装好了线程,实际上是HandlerThread和Handler的封装,这里具体分析里面的源码了,主要说一下IntentService的使用方法。

使用IntentService比较简单,只需要实现里面的onHandleIntent抽象方法即可,在里面可以加上一些耗时的操作,执行结束后,会自动调用stopself方法来结束服务。

可以自己验证,重写onDestroy方法,在里面打上Log,开启后看是否回调该方法。另外,可以验证下该线程的和主线程是否是一个线程。

不过有两点需要记住:

(1)就是onHandleIntent方法中的intent参数就是我们开启服务是传递的intent,通过这个intent也是传递一些参数给服务。

(2)该服务底层是通过looper来实现的消息遍历,顺序执行,所以你开启服务的先后是有顺序的,先到先得哦!

好了,就这些,没想到的情况可以补充哦!

练习代码地址

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,293评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,604评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,958评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,729评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,719评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,630评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,000评论 3 397
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,665评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,909评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,646评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,726评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,400评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,986评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,959评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,996评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,481评论 2 342

推荐阅读更多精彩内容