源码阅读--应用上下文环境Context

Context上下文环境包括哪些

Context继承结构
这里写图片描述

android应用是基于组件的,四大基本应用组件构成了基本的应用。开放给开发者的应用组件,打个比方就像一栋建筑的每个房间,我们像搭积木一样把每个房间合理摆放组成一栋建筑,但是现实中建筑并不是房间的简单堆砌,还要有地基,还要有钢筋结构的连接,有水电管线,有物业管理等配套的服务设施。同样的应用组件也要有运行的配套环境,这些环境在Context中进行了定义。
1.先看一下Context类的注释
Interface to global information about an application environment. This is an abstract class whose implementation is provided by the Android system. It allows access to application-specific resources and classes, as well as up-calls for application-level operations such as launching activities, broadcasting and receiving intents, etc.
提供应用环境的全局信息的接口,可以获取到应用自有的资源和class类,同时应用层级操作(启动activity,发送广播等)
看一下Context源码中的方法定义:上图罗列了部分方法定义getResources()、getDrawable()、getClassLoader()是获取到应用自有的资源和class类相关的方法,此外有startActivity()等方法进行组件级操作。
2.此外,还有一些对数据文件的操作:sp,文件,数据库;方法getSystemService()提供了获取系统服务的能力
总结一下,Context提供了以下应用上下文环境:
1.应用自有资源与代码
2.组件操作(组件启动,广播,Receiver注册等)
3.数据IO操作
4.系统服务获取
5.主线程关联

Context的结构设计采用了装饰者模式。Activity,Service和Application都直接或间接继承自ContextWrapper,这三个类很少对ContextWrapper方法进行重写(Activity处理较多),对而ContextWrapper把所有功能都委托给ContextImpl来实现,Context的基础功能基本上都在ContextImpl中实现。

资源管理与代码加载

资源管理

以getDrawable为例,看一下Context如何获取资源文件:

Context.java

 public final Drawable getDrawable(@DrawableRes int id){
     return getResources().getDrawable(id, getTheme());
 }

ContextImpl.java
这里写图片描述

默认会调用LoadedApk的getResources方法获取Resources对象。

LoadedApk.java
这里写图片描述
ActivityThread.java
这里写图片描述

可以看出所有的Resources创建都汇集到ResourcesManager这个类来进行。ResourcesManager采用单例模式,也就是说同一进程下的Resources对象是由同一个ResourcesManager创建的。具体的资源管理会在后面分析。

代码加载

java类加载遵循双亲委托模型,android同样遵循该模型,只是在ClassLoader的继承结构上有差异。看一下ClassLoader的创建:

ContextImpl.java
这里写图片描述
LoadedApk.java
这里写图片描述

在createOrUpdateClassLoaderLocked方法中,调用了ApplicationLoader的getClassLoader方法:

这里写图片描述

可以看到这里ClassLoader是PathClassLoader对象。
看一下PathClassLoader类的注释,
Android uses this class for its system class loader and for its application class loader(s).
这个类加载器用于加载安卓系统类和应用程序类,这里的应用必须是已安装的。这也说明上面的ClassLoader对象是PathClassLoader对象。
更多ClassLoader信息参考:Android动态加载之ClassLoader详解

LoadedApk

从前面可以看出,资源和代码的管理都用到了LoadedApk这个类。
在ActivityThread类中,提供了获取LoadedApk对象的方法

这里写图片描述
LoadedApk.java

loaded描述了一个已加载的apk的状态。下图展示了LoadedApk的主要成员,包括apk位置,资源目录,数据目录等,最主要的是ApplicationInfo,可以看到主要成员的设置跟ApplicationInfo是相关的。

这里写图片描述
这里写图片描述
这里写图片描述

数据操作

安卓的数据存储包括SharedPrefereces,File,DataBase,网络等方式,Context提供了部分数据源API包括Sp,File,DataBase。

Sp

Sp数据以xml文件形式存储在data/data/<包名>/preferens目录下。Context提供getSharedPreferences方法返回SharedPreferencesImpl对象

File

Context提供openFileInput和openFileOutput用于处理文件这里的文件默认是位于data/data/<包名>/files目录下的。
sd卡目录可以通过Environment.getExternalStorageDirectory()获取。Context也提供了一些Api获取sd卡目录,也是通过Environment

Database

Context提供openOrCreateDatabase创建数据库,但数据库相关操作一般是使用SQLiteOpenHelper

系统服务

Context定义了一系列Service常量名,可以通过getSystemService(String name)获取对应服务。

Context创建

Context使用了装饰这模式,Application等Context子类对象其实是封装了ContxetImpl的实现,通过持有的mBase对象(ContextImpl)实现具体操作。那么封装类和mBase是在什么时候关联的?

Application的创建

在应用进程启动以后,应用通过ActivityThread的main方法开始执行,先会bindApplication与AMS交互,在回调处理中会触发handleBindApplication方法,Application对象在此时创建。

Context关联

handleBindApplication
这里写图片描述

这里调用了LoadedApk的makeApplication方法
这里写图片描述
继续调用Instrumentation的newApplication
这里写图片描述
attach方法中调用了attachBaseContext在这里进行了Context关联
这里写图片描述

这里写图片描述

ContextImpl创建

在LoadedApk的makeApplication方法中调用了ContextImpl.createAppContext工厂方法。
ContextImpl类提供了三个静态工厂方法创建ContextImpl对象

这里写图片描述

LoadedApk是ContextImpl类中mPackageInfo的类型,一个重要成员。makeApplication中传入的参数是当前LoadedApk对象。再看一下前面makeApplication的调用

 Application app = data.info.makeApplication(data.restrictedBackupMode, null);
            mInitialApplication = app;

这里的data.info就是一个LoadedApk对象,创建也是在handleBindApplication方法中。

data.info = getPackageInfoNoCheck(data.appInfo,data.compatInfo);

ActivityThread提供getPackageInfo方法创建LoadedApk对象

猜你喜欢

转载自blog.csdn.net/yuanjw2014/article/details/78139585
今日推荐