前言
Android资源文件分为两类:
第一种是res目录下存放的可编译的资源文件,编译时,系统会自动在R.java中生成资源文件的ID,所以访问这种资源比较简单,通过在程序中调用R.id.filename即可。
另一种是assets目录下存放的原始资源文件,因为系统在编译的时候不会编译assets下的资源文件,所以我们不能通过R.id.filename的方式访问它们。那我们能不能通过该资源的绝对路径去访问它们呢?因为apk安装之后会放在/data/app/**.apk目录下,assets被绑定在apk里,以apk形式存在,并不会解压到/data/data/YourApp目录下去,所以我们无法直接获取到assets的绝对路径,因为它们根本就没有独立存在。
res/raw和assets的相同点:
两者目录下的文件在打包后会原封不动的保存在apk包中,不会被编译成二进制。
res/raw和assets的不同点:
1.res/raw中的文件会被映射到R.java文件中,访问的时候直接使用资源ID即R.id.filename即可;assets文件夹下的文件不会被映射到R.java中,访问的时候需要AssetManager类。
2.res/raw不可以有目录结构,而assets则可以有目录结构(在其目录下可以再建文件夹)
3.读取res/raw下的文件资源,通过以下方式获取输入流:InputStream is=getResources().openRawResource(R.id.filename); 读取assets下的文件资源,通过以下方式获取输入流:InputStream is =getResources()..getAssets().open("filename");
一.了解resources.arsc
1.找到resources.arsc
我们将目录显示形式换为Project,然后按如图所示的顺序点击目录,

,然后就会显示出这些东西

2.resources.arsc简介
在c++层build的时候,干了一个事情,就是生成如图箭头指向的那个文件。
那个文件是一个二进制文件,类似于一个数据库。我们说“资源加载”就是加载的这个文件。它存放着所有的资源信息。就是一个app的资源索引表。App资源根据配置发生变化,索引到相应的资源都要依赖它。
例如Android设备语言,屏幕设备尺寸不同时,app通过同样的ID但却能找到不同的资源进行显示。
“表”里面存放着比如资源类型,资源id,资源名称等等。左下角框起来的部分类似于数据库的表名,然后右边的ID/NAME/default这些类似于数据库的行和列。比如这里我拿一个数据库的图片过来

其中①就类似于resources.arsc,②就类似于左下角的哪些比如animator,然后③就类似于ID/NAME/default这些了。在这个二进制文件中标识了res中每一个资源所对应的信息。当我们去加载一个apk包以后,会有一个类去负责读取这个二进制文件的信息。那么是什么类呢?读取的过程是怎样的呢?下面就开始分析。
二.资源加载过程源码分析
放一张图

下面对图进行解释
1.首先进入ActivityThread类,然后找到
private void handleBindApplication(AppBindData data) {
(5429行)
然后在5695行完成了mInstrumentation的初始化
mInstrumentation = new Instrumentation();
关于Instrumentation。我们到源码中看它的定义
/**
* Base class for implementing application instrumentation code. When running
* with instrumentation turned on, this class will be instantiated for you
* before any of the application code, allowing you to monitor all of the
* interaction the system has with the application. An Instrumentation
* implementation is described to the system through an AndroidManifest.xml's
* <instrumentation> tag.
*/
我用谷歌翻译了一下
实现应用程序检测代码的基类。 在启用检测的情况下运行时,将在任何应用程序代码之前为您实例化该类,
从而使您可以监视系统与应用程序之间的所有交互。
通过AndroidManifest.xml的&lt; instrumentation&gt;
向系统描述了Instrumentation的实现。 标签。
我个人感觉还是不太懂,又找到了官方的定义
instrumentation can load both a test package and the application under test into the same process. Since the application components and their tests are in the same process, the tests can invoke methods in the components, and modify and examine fields in the components.
再谷歌翻译下,就是
Instrumentation可以将测试包和被测应用程序加载到同一个进程中运行。 由于应用程序组件及其测试代码在同一进程中,因此测试代码可以调用组件中的方法,并修改和检查组件中的字段。
所以大体了解到,这个类是管理Activity生命周期的。它可以在正常的生命周期下调控 控件/组件的运行。ok,了解这么多,足够了,让我们继续往下走
然后在5715行完成了app的初始化
app = data.info.makeApplication(data.restrictedBackupMode, null);
2.追踪makeApplication,了解下如何进行初始化的
public Application makeApplication(boolean forceDefaultAppClass,
Instrumentation instrumentation) {
...
ContextImpl appContext = ContextImpl.createAppContext(mActivityThread, this);
app = mActivityThread.mInstrumentation.newApplication(cl, appClass, appContext);
appContext.setOuterContext(app);
...
在这里创建了一个上下文appContext。
追踪createAppContext方法
static ContextImpl createAppContext(ActivityThread mainThread, LoadedApk packageInfo) {
if (packageInfo == null) throw new IllegalArgumentException("packageInfo");
ContextImpl context = new ContextImpl(

本文详细分析了Android中资源加载的过程,包括res/raw和assets的区别,重点介绍了resources.arsc文件的生成和作用,以及AssetManager在资源管理中的核心地位。通过对ActivityThread、Instrumentation和LoadedAPK的源码追踪,展示了资源加载的完整流程,强调了AssetManager在读取APK中Assets资源文件的重要性。
最低0.47元/天 解锁文章
1212

被折叠的 条评论
为什么被折叠?



