写给Android App开发人员看的Android底层知识(5)
(十)Service
Service有两套流程,一套是启动流程,另一套是绑定流程。我们做App开发的同学都应该知道。

1)在新进程启动Service
我们先看Service启动过程,假设要启动的Service是在一个新的进程中,分为5个阶段:
1)App向AMS发送一个启动Service的消息。
2)AMS检查启动Service的进程是否存在,如果不存在,先把Service信息存下来,然后创建一个新的进程。
3)新进程启动后,通知AMS说我可以啦。
4)AMS把刚才保存的Service信息发送给新进程
5)新进程启动Service
我们仔细看一下这5个阶段:
第1阶段

和Activity非常像,仍然是通过AMM/AMP把要启动的Service信息发送给AMS。
第2阶段
AMS检查Service是否在Manifest中声明了,没声明会直接报错。
AMS检查启动Service的进程是否存在,如果不存在,先把Service信息存下来,然后创建一个新的进程。
在AMS中,每个Service,都使用ServiceRecord对象来保存。
第3阶段
Service所在的新进程启动的过程,就和前面介绍App启动时的过程差不多。
新进程启动后,也会创建新的ActivityThread,然后把ActivityThread对象通过AMP传递给AMS,告诉AMS,新进程启动成功了。
第4阶段
AMS把传进来的ActivityThread对象改造为ApplicationThreadProxy,也就是ATP,通过ATP,把要启动的Service信息发送给新进程。
第5阶段

新进程通过ApplicationThread接收到AMS的信息,和前面介绍的启动Activity的最后一步相同,借助于ActivityThread和H,执行Service的onCreate方法。在此期间,为Service创建了Context上下文对象,并与Service相关联。
需要重点关注的是ActivityThread的handleCreateService方法,

你会发现,这段代码和前面介绍的handleLaunchActivity差不多,都是从PMS中取出包的信息packageInfo,这是一个LoadedApk对象,然后获取它的classloader,反射出来一个类的对象,在这里反射的是Service。
四大组件的逻辑都是如此,所以我们要做插件化,可以在这里做文章,换成插件的classloader,加载插件中的四大组件。
至此,我们在一个新的进程中启动了一个Service。
2)启动统一进程的Service
如果是在当前进程启动这个Service,那么上面的步骤就简化为:
1)App向AMS发送一个启动Service的消息。
2)AMS例行检查,比如Service是否声明了,把Service在AMS这边注册。AMS发现要启动的Service就是App所在的Service,就通知App启动这个Service。
3)App启动Service。
我们看到,没有了启动新进程的过程。
3)在同一进程绑定Service
如果是在当前进程绑定这个Service呢?过程是这样的:
1)App向AMS发送一个绑定Service的消息。
2)AMS例行检查,比如Service是否声明了,把Service在AMS这边注册。AMS发现要启动的Service就是App所在的Service,就先通知App启动这个Service,然后再通知App,对Service进行绑定操作。
3)App收到AMS第1个消息,启动Service,
4)App收到AMS第2个消息,绑定Service,并把一个Binder对象传给AMS
5)AMS把接收到的Binder对象,发送给App
6)App收到Binder对象,就可以使用了。
你也许会问,都在一个进程,App内部直接使用Binder对象不就好了,其实吧,要考虑不在一个进程的场景,代码又不能写两份,两套逻辑,所以就都放在一起了,即使在同一个进程,也要绕着AMS走一圈。
第1阶段:App向AMS发送一个绑定Service的消息。

第4阶段:处理第2个消息

第5阶段和第6阶段:
这一步是要仔细说的,因为AMS把Binder对象传给App,这里没用ATP和APT,而是用到了AIDL来实现,这个AIDL的名字是IServiceConnection。

ServiceDispatcher的connect方法,最终会调用ServiceConneciont的onServiceConnected方法,这个方法我们就很熟悉了。App开发人员在这个方法中拿到connection,就可以做自己的事情了。
好了,关于Service的底层知识,我们就全都介绍完了。当你再去编写一个Service时,是否感觉对这个组件理解的更透彻了呢?
下一篇我们聊一聊BroadcastReceiver。
写给Android App开发人员看的Android底层知识(5)的更多相关文章
- 写给Android App开发人员看的Android底层知识(1)
这个系列的文章一共8篇,我酝酿了很多年,参考了很多资源,查看了很多源码,直到今天把它写出来,也是战战兢兢,生怕什么地方写错了,贻笑大方. (一)引言 早在我还是Android菜鸟的时候,有很多技术我都 ...
- 写给Android App开发人员看的Android底层知识(2)
(五)AMS 如果站在四大组件的角度来看,AMS就是Binder中的Server. AMS全称是ActivityManagerService,看字面意思是管理Activity的,但其实四大组件都归它管 ...
- 写给Android App开发人员看的Android底层知识(6)
(十一)BroadcastReceiver BroadcastReceiver,也就是广播,简称Receiver. 很多App开发人员表示,从来没用过Receiver.其实吧,对于音乐播放类App,用 ...
- 写给Android App开发人员看的Android底层知识(3)
(七)App启动流程第2篇 书接上文,App启动一共有七个阶段,上篇文章篇幅所限,我们只看了第一阶段,接下来讲剩余的六个阶段,仍然是拿斗鱼App举例子. 简单回顾一下第一阶段的流程,就是Launche ...
- 写给Android App开发人员看的Android底层知识(7)
(十二)ContentProvider (1)ContentProvider是什么? ContentProvider,简称CP. 做App开发的同学,尤其是电商类App,对CP并不熟悉,对这个概念的最 ...
- 写给Android App开发人员看的Android底层知识(8)
(十)PMS及App安装过程 PMS,全称PackageManagerService,是用来获取Apk包的信息的. 在前面分析四大组件与AMS通信的时候,我们介绍过,AMS总是会使用PMS加载包的信息 ...
- 写给Android App开发人员看的Android底层知识(4)
(八)App内部的页面跳转 在介绍完App的启动流程后,我们发现,其实就是启动一个App的首页. 接下来我们看App内部页面的跳转. 从ActivityA跳转到ActivityB,其实可以把Activ ...
- 一看就懂的Android APP开发入门教程
一看就懂的Android APP开发入门教程 作者: 字体:[增加 减小] 类型:转载 这篇文章主要介绍了Android APP开发入门教程,从SDK下载.开发环境搭建.代码编写.APP打包等步骤 ...
- 谋哥:App开发人员的苦逼不值得怜悯!!
[谋哥每天一干货,第四十篇] 为什么取这个标题呢?由于昨天一些本来"支持"谋哥的人看到谋哥搞收费VIP群,认为谋哥赚苦逼开发人员的钱非常不道德,且说谋哥我写的东西都 ...
随机推荐
- 云计算之路-阿里云上:数据库连接数过万的真相,从阿里云RDS到微软.NET Core
在昨天的博文中,我们坚持认为数据库连接数过万是阿里云RDS的问题,但后来阿里云提供了当时的数据库连接情况,让我们动摇了自己的想法. 帐户 连接数 A 4077 B 3995 C 741 D 698 E ...
- 如何快速将本地项目托管到到github上?
1,打开你的本地项目文件夹,比如 test-demo: 2,打开github(没有github的要自己注册下), 点击new repository 3,填写项目信息,创建项目 4,复制新建的项目url ...
- JAVA经典算法40题
1: JAVA经典算法40题 2: [程序1] 题目:古典问题:有一对兔子,从出生后第3个月起每个月都生一对兔子,小兔子长到第四个月后每个月又生一对兔子,假如兔子都不死,问每个月的兔子总数为多少? 3 ...
- 秒懂JS对象、构造器函数和原型对象之间的关系
学习JS的过程中,想要掌握面向对象的程序设计风格,对象模型(原型和继承)是其中的重点和难点,拜读了各类经典书籍和各位前辈的技术文章,感觉都太过高深,花费了不少时间才搞明白(个人智商是硬伤/(ㄒoㄒ)/ ...
- Layoutparams理解
一. layoutparams是什么LayoutParams继承于Android.View.ViewGroup.LayoutParamsLayoutParams只是ViewGroup的一个内部类 vi ...
- Why we don’t recommend using List<T> in public APIs
不推荐List<T>做API原因有如下两点:1.首先List<T> 设计之初就没有设计成可扩展的,我们不能重新其任何方法.这就意味着,我们操作List<T>的时候却 ...
- SecureCRT中vim乱码问题
Options->Session Options,接着在Terminal->Appearance页签中设定Character encoding为Unicode (UTF-8).
- c标签和foreach循环不能加载
需要同时导入2个包: jstl.jar和standard.jar(大多数时候只会注意到jstl包,而忽视了standard包) 代码: c标签的写法 <%@ taglib prefix=&quo ...
- 深入tornado中的ioLoop
本文所剖析的tornado源码版本为4.4.2 ioloop就是对I/O多路复用的封装,它实现了一个单例,将这个单例保存在IOLoop._instance中 ioloop实现了Reactor模型,将所 ...
- bootstrap快速入门笔记(七)-表格,表单
一,表格 1,<table>中加.table类 2,条纹表格:通过 .table-striped 类可以给 <tbody> 之内的每一行增加斑马条纹样式. **跨浏览器兼容性: ...