Android源码分析-全面理解Context (二)
2024-04-09 17:50:21  阅读数 712

接着上篇Android源码分析-全面理解Context (一)继续讲:

Service对象中ContextImpl的创建

通过查看源码发现和Activity,Application是一致的。分析到这里,那么三者的Context有什么区别呢,有一些细节是需要注意的:Dialog的使用是需要Activity

在桌面上我们采用Application的Context无法弹出普通对话框等等。

Context对资源的访问

很明确,不同的Context得到的都是同一份资源,请看下面的分析

我们得到资源的方式为context.getResources,而真正的实现位于ContextImpl中的getResources方法,在ContextImpl中有一个成员变量mResources

它就是getResources方法返回的结果,mResources的赋值代码为:

下面来看一下ResourcesManager的getTopLevelResources方法,它的这个方法是这样的:在ResourcesManager中,所有的资源对象都被存储在ArrayMap中,首先根据当前的请求参数去查找资源,如果找到了就返回,否则就创建一个资源对象放在ArrayMap中,有一点需要说明的是为什么会有多个资源对象,因为在res下面存在多个适配不同设备,不同分辨率,不同系统版本的目录,按照android系统的设计,不同设备在访问同一个应用的时候访问资源可以不同,比如drawable-hdpi和drawable-xhdpi就是典型的例子。



根据上述代码中的请求机制,再加上ResourcesManager采用单例模式,这就保证了不同的ContextImpl访问的是同一套资源,注意这里说的同一套资源未必是同一个资源,因为资源可能位于不同的目录,在设备参数和显示参数不变的情况下,不同的ContextImpl访问到的是同一份资源,尽管Application,Activity,Service都有自己的ContextImpl,并且每个ContextImpl都有自己的mResources成员,但是由于它们的mResources成员都是来自唯一的ResourcesManager实例,所以它们实际上还是同一个内存地址。

getApplication和getApplicationContext的区别:

getApplication返回结果为Application,且不同的Activity和Service返回的Application均为同一个全局对象,在ActivityThread内部有一个列表专门用于维护所有应用的application

getApplicationContext返回的也是Application对象,只不过返回类型为Context,看看它的实现

上面代码中mPackageInfo是包含当前应用的包信息,比如包名,应用的安装目录等,原则上来说作为第三方应用,包信息不可能为空,在这种情况下,getApplicationContext返回的对象和getApplication是同一个。但对于系统应用,包信息可能为空。

综上所述:两者的区别仅仅是返回类型不同。

应用中Context数量

一个应用中Context的数量等于Activity的个数+Service的个数+Application个数(通常单进程APP为1)。