【转载】Android Context 到底是什么?
什么是Context?
一个Context意味着一个场景,一个场景就是我们和软件进行交互的一个过程。比如当你使用微信的时候,场景包括聊天界面、通讯录、朋友圈,以及背后的一些数据。
那么从程序的角度来看,Context是什么?其实一个Activity就是一个Context,一个Service也是一个Context。
一个应用程序可以认为是一个工作环境,用户在这个工作环境中会切换到不同的场景,这就像一个助理,他可能需要接待客人,可能还要打印文件,还可能接听电话,而这些就称之为不同的场景,助理可称之为一个应用程序。
Activity类的确是基于Context,而Service类也是基于Context。Activity除了基于Context类外,还实现了一些其他重要的接口,从架构设计的角度看,interface仅仅是某些功能,而extends才是类的本质,即Activity的本质是一个Context,其所实现的其他接口只是为了扩充Context的功能而已,扩充后的类称之为一个Activity或Service。
一个应用程序中应该有多少个Context对象
我们在应用程序开发中经常会调用Context的一些方法,这些方法看起来似乎会返回一些全局的对象,而不仅仅是某个Activity,可能会有点疑问,一个应用程序到底有多少个Context对象呢?比如,Context.getResources()返回该应用程序所对应的Resource类对象,无论从哪个Activity中调用,都会返回同一个Resource对象。
- 一个Activity就是一个场景(Context),一个Service也是一个场景,所以,应用程序中有多少个Activity或者Service就会有多少个Context对象。
- getResource()等方法返回的是同一个全局对象。
Context 相关类是怎么继承的呢?

Context类本身是一个纯abstract类。为了使用方便又定义了Context包装类-ContextWrapper,ContextWrapper构造函数中必须包含一个真正的Context引用,同时ContextWrapper中有attachBaseContext()用于给ContextWrapper对象中指定真正的Context对象。
ContextThemeWrapper内部包含了与主题相关的接口,这里的主题就是指在AndroidManifest.xml中通过Android:theme为Application或者Activity指定的主题。
只有Activity才需要主题,Service不需要主题的,所以Service直接继承与ContextWrapper。
ContextImpl类真正实现了Context中所有的函数,我们所调用的各种Context类的方法其实实现均来自于该类。
什么时候创建Context?
每一个应用程序在客户端都是从ActivityThread类开始的,创建Context对象也是在该类中完成,具体创建ContextImpl类的地方一共有6处:
- PackageInfo.makeApplication()
- performLaunchActivity()
- handleCreateBackupAgent()
- handleCreateService()
- handleBindApplication()
- attach()
其中attach()方法仅在Framework进程启动时调用,应用程序运行时不会调用到该方法。
Application对应的Context
程序第一次启动时,会辗转调用到makeApplication()方法。具体代码如下:
ContextImpl appContext = new ContextImpl();
appContext.init(this,null,mActivityThread);
....
appContext.setOuterContext(app);
Activity对应的Context
启动Activity时,Ams会通过IPC调用到ActivityThread的scheduleLaunchActivity()方法,该方法包含两种参数。一种是ActivityInfo,这是一个实现了Parcelable接口的数据类,意味着该对象是Ams创建的,并通过IPC传递到ActivityThread;另一种是其他的一些参数。
scheduleLaunchActivity()方法中会根据以上两种参数构造一个本地ActivityRecord数据类,ActivityThread内部会为每一个Activity创建一个ActivityRecord对象,并使用这些数据对象来管理Activity。
然后会调用handleLaunchActivity(),再调用performLaunchActivity(),该方法中创建ContextImpl的代码如下:
ContextImpl appContext = new ContextImpl();
appContext.init(r.packageInfo,r.token,this);
appContext.setOuterContext(activity);
在performLaunchActivity()开始执行时,会为r.packageInfo变量赋值。r.packageInfo对象的PackageInfo对象和Application对应的packageInfo对象是同一个。
Service对应的Context
启动Service时,Ams会通过IPC调用到ActivityThread的scheduleCreateService()方法,该方法也包含两种参数。第一种是ServiceInfo,这是实现了一个Parcelable接口的数据类,该对象由AmS创建,并通过IPC传递到ActivityThread内部;第二种是其他参数。
在scheduleCreateService()方法中,会使用以上两种参数构造一个CreateServiceData的数据对象,ActivityThread会为其所包含的每一个Service创建该数据对象,并通过这些对象来管理Service。
然后在执行handleCreateService()方法,创建ContextImpl对象代码如下:
ContextImpl appContext = new ContextImpl();
appContext.init(packageInfo,null,this);
...
appContext.setOuterContext(service);
Service对应的Context对象内部的mPackageInfo与Activity、Application中是完全相同的。
这几个Context之间的关系
从以上可以看出,创建Context对象的过程基本上是相同的,不同的仅仅是针对Application、Activity、Service使用了不同的数据对象。
一个应用程序包含的Context个数应该为:Context个数 = Service个数+Activity个数+1,最后的1是Application类本身也会对应一个Context对象。
应用程序中包含多个ContextImpl对象,而内部变量mPackageInfo却指向同一个PackageInfo对象,这种设计结构一般意味着ContextImpl是一种轻量级类,而PackageInfo是一个重量级类。事实上确实是这样,ContextImpl中的大多数进行包操作的重量级函数实际上都是转向了mPackageInfo对象相应的方法,也就是事实上调用了同一个PackageInfo对象。
【转载】Android Context 到底是什么?的更多相关文章
- Android Context 是什么?
andorid 开发(42) 版权声明:本文为博主原创文章,未经博主允许不得转载. [转载请注明出处:http://blog.csdn.net/feiduclear_up CSDN 废墟的树] PS ...
- Android Context完全解析
Context类型 我们知道,Android应用都是使用Java语言来编写的,那么大家可以思考一下,一个Android程序和一个Java程序,他们最大的区别在哪里?划分界限又是什么呢?其实简单点分析, ...
- Android Intent到底能做些什么
Android Intent到底能做些什么 原文:http://www.toutiao.com/i6348296465147757058/?tt_from=mobile_qq&utm_camp ...
- 【42】android Context深度剖析
android程序和java程序的区别 Android程序不像Java程序一样,随便创建一个类,写个main()方法就能跑了,而是要有一个完整的Android工程环境,在这个环境下,我们有像Activ ...
- Android Context完全解析,你所不知道的Context的各种细节
Context相信所有的Android开发人员基本上每天都在接触,因为它太常见了.但是这并不代表Context没有什么东西好讲的,实际上Context有太多小的细节并不被大家所关注,那么今天我们就来学 ...
- Android面试收集录18 Android Context详解
Activity mActivity =new Activity() 作为Android开发者,不知道你有没有思考过这个问题,Activity可以new吗?Android的应用程序开发采用JAVA语言 ...
- Android Context介绍
转载(Android Context完全解析与各种获取Context方法):https://www.cnblogs.com/chenxibobo/p/6136693.html
- Android Context完全解析与各种获取Context方法
Context类型 我们知道,Android应用都是使用Java语言来编写的,那么大家可以思考一下,一个Android程序和一个Java程序,他们最大的区别在哪里?划分界限又是什么呢?其实简单点分析, ...
- [转载]Android开发者必须深入学习的10个应用开源项目
[转载]Android开发者必须深入学习的10个应用开源项目 原文地址:Android开发者必须深入学习的10个应用开源项目(http://blog.sina.com.cn/s/blog_7b8a63 ...
随机推荐
- java对象的实例化过程
简单类对象的实例化过程 1.在方法区加载类: 2.在栈内存申请空间,声明变量P: 3.在堆内存中开辟空间,分配对象地址: 4.在对象空间中,对对象的属性进行默认初始化,类成员变量显示初始化: 5.构造 ...
- day05生成随机数、do-while循环、for循环、循环流控(break和continue)、循环嵌套
复习 1.多重if 一个条件触发的情况在3种或以上时 if(<条件1>){ //条件1为真时运行 }else if(<条件2>){ //条件1为假,条件2为真时运行 }else ...
- 两种最常用的 HTTP 操作方法是:GET 和 POST。
什么是 HTTP? 超文本传输协议(HTTP)的设计目的是保证客户机与服务器之间的通信. HTTP 的工作方式是客户机与服务器之间的请求-应答协议. web 浏览器可能是客户端,而计算机上的网络应用程 ...
- 分享几个好看又实用的PPT网站~
一,优品PPT[http://www.ypppt.com/] 一个有情怀的免费PPT模板下载网站!拥有非常多很精美的PPT模板,分类齐全,我们可以选择自己喜欢的PPT模板下载套用就可以了. 二,扑奔P ...
- 开启Hyper-V
开启Hyper-V 添加方法非常简单,把以下内容保存为.cmd文件,然后以管理员身份打开这个文件.提示重启时保存好文件重启吧,重启完成就能使用功能完整的Hyper-V了. pushd "%~ ...
- [转]BEC Vantage
https://www.examenglish.com/BEC/BEC_Vantage.html https://www.cambridgeenglish.org/exams-and-tests/bu ...
- 为Dynamics 365 USD设置打开调试面板的自定义快捷键
我是微软Dynamics 365 & Power Platform方面的工程师罗勇,也是2015年7月到2018年6月连续三年Dynamics CRM/Business Solutions方面 ...
- mybatis+sqlServer 实现insertOrUpdate
这两天遇到一个头疼的问题,我们系统需要请求第三方数据,第三方收到请求后会生成相应的数据并入库,我们通过定时任务将第三方数据同步到我们数据库.当我们发送请求后第三方会立即返回一个值,我们会根据返回值去数 ...
- python-参数化-(1)(手机号码)
一.生成手机号码,此处并没有写成类或者函数形式,上代码 import random #指定手机号码前三位格式,并随机返回一个区号,关于random参数化的相关部分自行了解type_mobile = [ ...
- js 运算的内置函数
// 一.Math.round()作用:四舍五入返回整数.(返回参数+0.5后,向下取整) // Math.round(5.57) //返回6 // Math.round(2.4) //返回2 // ...