15.资源访问机制

实际上styleable仅仅是在R.java中增加了一个int[]数组而已,aapt为每一个attr分配一个指定的id值,这个数组的内容正是该styleable所包含的所有attr的id值。

attr的名称在该应用程序范围中必须是唯一的。如果在attr后面仅仅有一个name而没有format,那么就是引用,否则就是声明,只能有一个声明,但可以有多个引用。

res目录包含了开发工程中res目录下除了values以外的所有内容,一般包含各种layout和drawable,layout的内容都是以二进制xml格式保存的,而所有的drawable图像资源都是未经压缩过的原始图像文件。一般所见的png,jpg图像文件本身就是已经压缩过的文件,因此,无需再压缩。

resources.arsc十一种二进制格式的文件,与二进制xml完全不同。aapt在对资源文件进行编译时,回味每一个资源分配唯一的id值,程序在执行时会根据这些id值读取特定的资源,而resources.arsc文件正式包含了所有id值的一个数据集合。在该文件中,如果某个id对应的资源是String或者数值(int,long),那么该文件会直接包含相应的值,如果id对应的资源是某个layout或者drawable资源,那么该文件会存入对应资源的路径地址。

APK程序在执行时,并不是直接从APK中读取程序文件,可以这么认为,APK是一种具有安装格式的文件,安装后将是另外一个样子。

与安装后相关的目录如下:

  • /data/app 当安装一个APK时,系统首先会把该文件复制到该目录下,如果是系统程序,则一般位于/system/app目录下。
  • /data/dalvik-cache 每个apk中都包含一个classes.dex文件,系统在安装apk程序时,会把该apk中包含的classes.dex解压出来放到该目录下,为的是当用户启动该程序时能够快速读取类文件,系统应用程序中的classes.dex文件同样也放到该目录下。该目录中的文件命名格式为“apk路径+classes.dex”,其中apk路径中的子目录符号用@代替。如data@app@com.android.contacts.apk@classes.dex 。任何程序都可以读写该目录,这就为类的动态装载提供了可能。
  • /data/data 每个应用程序都有自己的数据目录,目录名称为应用程序的包名,所有的数据目录都在改目录下。

并不是说程序安装好后,/data/app或者/system/app目录下的原始文件就可以删除了,事实上,当程序运行时,所需要的资源文件都要在原始文件中读取。加载资源时,首先加载resources.arsc,然后根据id值找到指定的资源。

构造Resources对象需要先构造一个AssetManager对象,然后把这个对象作为Resources构造函数的参数即可。

AssetManager其实并不只是访问项目中res/assets目录下的资源,而是访问res下所有的资源。

AssetManager类中的几个关键函数都是native实现的,其中addAssetPath(resDir)非常关键,它为所创建的AssetManager对象添加一个资源路径,剩下的事情就由AssetManager内部完成了,内部会从指定的路径处获取任何资源。

AssetManager类构造函数中native的方法init的作用是初始化AssetManager的内部环境变量,而初始化过程的一个关键任务是把framework中的资源路径添加到该AssetManager对象中。

使用PackageManager获取Resources对象的代码如下:

PackageManage pm = mContext.getPackageManager();
pm.getResourcesForApplication("com.solarexsoft.test");

系统资源是在zygote进程启动时被加载的,并且只有当加载了系统资源之后才开始启动其他应用进程,从而实现其他应用进程共享系统资源的目标。

在Resources类中相关的资源读取函数中需要将读取到的资源缓存起来,以便以后调用,为了这个目的,Resources类中定义了四个静态变量。

private static boolean sPreloaded;
private static final LongSparseArray<Drawable.ConstantState>[] sPreloadedDrawables;
private static final LongSparseArray<Drawable.ConstantState> sPreloadedColorDrawables
            = new LongSparseArray<>();
private static final LongSparseArray<android.content.res.ConstantState<ComplexColor>>
            sPreloadedComplexColors = new LongSparseArray<>();

static属性导致Resources类在被应用程序进程创建新的Resources对象时,保存了Zygote进程中所预装的资源。

在Resources的具体资源读取方法中,会判断mPreloaded是否为true,如果是,则同时把读取到的资源存储到三个static中的相关列表中,否则,把读取到的资源放到非静态列表等相关变量中,这些变量的作用范围是调用者所在的进程。

results matching ""

    No results matching ""