ResourcesLoader + ResourcesProvider:Android 11 中的动态扩展资源的搜索和加载方式

ResourcesLoader、ResourcesProvider详解


在安卓开发课程中经常需要翻阅官方文档,在一次偶然翻到Android 11预览版新特性的时候注意到一个新的更新:资源加载器, 引入了一个新 API,允许应用动态扩展资源的搜索和加载方式。
在网上查找相关的知识想要学习一下,发现介绍的文章少之又少,所以这里我打算从Android官方文档出发,详细写一下这个两个新的API,顺便附上一个我摸索的例子。

官方文档概述

官方文档对这一新的API概述介绍如下:

资源加载器 “Android 11 引入了一个新 API,允许应用动态扩展资源的搜索和加载方式。新的 API 类 ResourcesLoader 和 ResourcesProvider 主要负责提供新功能。两者协同作用,可以提供额外的资源,或修改现有资源的值。ResourcesLoader 对象是向应用的 Resources 实例提供 ResourcesProvider 对象的容器,而 ResourcesProvider 对象提供从 APK 和资源表加载资源数据的方法。此 API 的一个主要用例是自定义资源加载。您可以使用 loadFromDirectory() 创建一个 ResourcesProvider,用于重定向基于文件的资源的解析,从而让其搜索特定目录,而不是应用 APK。您可以通过 AssetManager API 类中的 open() 系列方法访问这些资源,就像访问 APK 中绑定的资源一样。”

这一段话就完成介绍了这个资源加载器的内容,并且给了一个可能可以用到的用例。

一些预备知识

Q1:什么是资源?他们怎么分类?区别是什么?

官方文档 “资源是指代码使用的附加文件和静态内容,例如位图、布局定义、界面字符串、动画说明等。”

资源分为两类:原始资源 assets外部化应用资源res

  • res: 外部化应用资源后,可以用id来访问相应的资源。应当将各类资源放在项目res/目录下的特定子目录中,否则将会编译出错。
    res目录下有许多子目录,例如color/ 定义颜色状态,drawable/ 位图文件,layout/ 布局文件等等。
  • assets: 可以自行创建assets文件夹,里面存放需要用到的资源,值得注意的是,开发过程中并不会为其在添加id,可以用普通文件的访问方式访问这些原始资源,一般利用AssetManager来读取原始资源。

Q2:如何利用AssetManager来读取原始资源?
保存在 assets/ 目录中的文件没有资源 ID,因此不能通过 id引用它们,通常情况下我们利用AssetManager来读取。
这里具体介绍一下open方法,其他介绍见 官方文档
p1
AssetManager允许我们通过文件的名称来找到指定的资源,并且通过例如上图的open方法来获取一个InputStream类型的返回值以便我们操作。通常情况下我们通过上下文方式来获取其对象,举个小例子:

AssetManager am = getAssets();
//AssetManager am = AssetManager.class.newInstance();
InputStream is1 = am.open("demo2.png");
Bitmap bitmap1 = BitmapFactory.decodeStream(is1);
iv.setImageBitmap(bitmap1);

在这里accessMode使用的是缺省值:ACCESS_STREAMING

有话说: 值得注意的是,我们在用Resources类的时候也可以读取资源,这里虽然查询的是id,但是其本质上是拿id查找resources.arsc,获得filename后再利用AssetManager查找到具体资源。

Q3:什么是resources.arsc?
简单来说resources.arsc就是一个资源索引表,官方文档中也叫这类文件:resources table。这是一个预定义好的数据结构,我也是花了很长的时间去查资料弄懂了这个文件,这里放一个我看的参考:链接,在这我就不再写过多关于resources.arsc的介绍了。(在后面写从目录动态加载资源时要用到这个文件)

Q4:为什么要动态扩展资源?
通常我们封装一个App,其资源(原始资源和外部化资源)都是全部放到了这个APK中,而动态扩展资源则允许我们从移动设备的外部存储中自定义地读取我们需要的资源,非常的方便。

Android R中的动态扩展资源方式

新的 API 类 ResourcesLoader 和 ResourcesProvider 实现了可以提供额外的资源,或修改现有资源的值的方式。
p2
可以很清楚的得出,我们需要用 ResourcesProvider类中的相应方法来创建一个ResourcesProvider,其主要用于自定义解析指定目录的基于文件的资源,或者从其他APK中解析资源。接着我们可以通过ResourcesLoader来装这个Provider,而ResourcesLoader对象则负责向Resources实例提供一个容器。
于是我们得到了一个动态扩展资源的基本步骤:
1.创建ResourcesProvider,其加载资源有两种方法,从APK(.apk)或是资源表(resources tables,eg. resources.arsc
2.创建ResourcesLoader对象,并且添加上面我们已经创建好的ResourcesProvider
3.创建Resources对象,添加我们写好的Loaders
4.利用AssetManager类中的方法来访问这些数据

内容一:ResourcesProvider类详解

有话说: 由于网上的资料少之又少,所以我对比着官方文档的中英文概述自学了一番,水平有限也许有理解不当的地方,欢迎讨论。

首先附上官网文档:链接

Content1:该类的基本作用是什么?
p3
ResourcesProvider 对象提供从 APK 和资源表加载资源数据的方法。也就是说我们可以通过这个类提供的方法来自定义解析外部资源,通常情况下,直接解析APK文件,但是如果是解析目录,需要在该目录下有resources.arsc这一资源索引表,并且待加载的资源也是在该目录下的assets/ 子目录下,下文将会用一个实例来具体介绍。

Content2:该类有哪些常用的方法?
p4
官网文档中给出了其public方法(主要是创建ResourcesProvider对象的一些方法)和protected方法(垃圾回收的相关方法),这些方法都是在Android R中添加的。
下面介绍两种资源解析方式的一般方法(这里假定参数AssetsProvider为null,AssetsProvider的介绍见官方文档:链接,其提供允许ResourcesProvider指定或覆盖基于文件的资源或assets值的回调 ):

  • loadFromApk方法
    p5
    从APK中解析和加载资源。
    这是一个静态方法,返回的是一个ResourcesProvider对象。形参是一个ParcelFileDescriptor对象,这是一个在API 1中添加的类(具体介绍见官方文档:链接)这里我们就拿当前的情况来说明其中的一个方法。
    这里我使用open来获得我们所需要的APK,下图是它的结构:
    p6
    p7
    举个小例子:
File f = new File("/data/data/com.example.article_demo/cache/demo1.apk"
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

x1Nge.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值