1.背景
作为一个Android新手,每次看到使用Context作为参数时,都有点焦虑,有时候传this就可以,有时候又不行,不知道为什么可以,为什么又不可以,根本原因还是对Context是一知半解,偏偏很多地方用到Context作为参数,一直一知半解下去不是办法,有必要研究一下Context究竟是什么。
2.什么是Context?
Context中文意思是上下文,在小学语文课时,我们肯定接触过联系上下文理解词语的题目,“上下文”指的是语境,我们对语境的含义肯定是比较了解,一是小学刷那么多题目,二是现实生活中也常碰到,当你暗恋的对象对你说,你真是个好人,你得根据所处的具体情景进行推断,这句话是真夸你还是委婉拒绝了你,那么程序开发里“上下文”的语义是否和语文课里“上下文”的语义一样?
答案是一样的,在程序中,上下文指的是应用程序/对象当前状态,例如C语言中,简单一段c=a+b代码,要能运行起来,首先是a和b得赋值,a和b赋值了,a和b的赋值状态是c=a+b能否运行的上下文,而a和b赋值,运行c=a+b也不是直接能运行,还得main函数先运行起来,main函数运行状态又是main函数里各个代码运行的上下文。
在C语言中,我们不需要特别纠结于上下文这个概念,不影响写代码,但确实也有上下文概念,所谓的周易里说的“百姓日用而不知”,但在Android平台上,特别引入Context作为参数,用的地方还特别多,这就必须得纠结Context概念了。
为什么Android里需要Context作为参数?
我个人理解是为了程序员开发。例如四大组件之一的Activity,是在完整的工程环境下已经封装好了,在封装过程中已经考虑了运行环境的适配,组件生命周期的管理,页面布局资源的调度等,这些就是所谓的上下文,在这个上下文背景下,程序员只需要继承,即可在里面加上自己代码,让程序运行起来,而不需要从零开始编写。继续用上述的C语言例子来理解是,假设系统帮我们写好了main函数,这就是一个上下文封装,我们不用自己写main即可加上我们的代码运行起来。这也是为什么Android系统的四大组件不能直接new出来,因为不是一个简单的对象,而是需要有一个上下文环境,只能继承已经封装好的。
那么Context作为参数起什么作用?这在Google给出的Context的官方定义已经明牌提示了:
与有关应用程序环境的全局信息的接口。这是一个抽象类,其实现由Android系统提供。它允许访问特定于应用程序的资源和类,以及执行应用程序级操作(例如启动Activity,广播和接收Intent等)。
说实话,虽然官方定义清晰定义了Context功能,根据这个定义,理解启动Activity容易,因为Activity必须在一定上下文才能启动,这在前面已经解释了,但这个定义没解释清楚为什么Context能够访问资源。
对啊,为什么?
我的理解是,Context相当于把当前Android系统上下文环境赋值到Context这个参数里,也就是告诉我们当前程序所处的环境,而这环境由各种各样资源堆积成的,因此能够通过Context来访问环境背后的资源。
3.Context类继承图
我们来看一下Context的继承关系,从图上可以看出,Context下有两个具体的实现类,其中的ContextWrapper是封装类,ContextImpl是实现类,封装类负责貌美如花,ContextImpl负责赚钱养家,意思是ContextWrapper类基本是Context方法的再封装,而里面所用到的方法,是由ContextImpl实现的,这种设计模式可以讲接口和实现分类。
ContextWrapper由三个子类继承,其中两个是老熟人Application和Service,另外一个是ContextThemeWrapper类,顾名思义,该类包含了与主题(Theme)相关的接口,而继承ContextThemeWrapper类的是Activity,因为Activity是界面组件,需要主题,而Application和Service是无界面,因此不需要和ContextThemeWrapper搭上关系。
从继承图还可以看出,Context有Application,Service和Activity三个种类,他们的使用还是有差别的,网上有一个图(如下)对三个种类的Context使用的差别进行总结
原表格带注,意思是有些No的地方其实也是可行的,但不推荐,这里不写注了,直接按表格的建议。
表格中可以看到,Activity类的Context功能最全,和UI相关的选择Activity类准没错,毕竟是直接继承了主题类Context,也是四大组件里唯一界面的,除了UI,Application类都可以操作,现在程序员经常开发一个全局Application Context作为通用工具恐怕也是因为如此,但切记不能用于操作UI。
另外表格中混入Content Provider和BroadcastReceiver,看Context继承关系图中并没有这两货啊,这是因为这两货的的内部方法中都有一个context。
最后,作为一个小白,尝试通过一面写一面理解,可能对Context理解有偏差,如有错漏,欢迎指正。
参考目录
1.https://www.cnblogs.com/chenxibobo/p/6136693.html
2.https://stackoverflow.com/questions/3572463/what-is-context-on-android#
3.https://my.oschina.net/youranhongcha/blog/1807189