Android资源管理利器Resources和AssetManager
前言 :
Android工程在运行的时候往往需要引用资源。使用 Resources 来获取 res 目录下的各种与设备相关的资源。而使用 AssetManager 来获取 assets 目录下的资源。
资源包括系统资源、工程资源、第三方资源、插件资源等,分为两类:
- res目录下存放的可编译的资源文件,编译时,系统会自动在R.java中生成资源文件的ID,所以访问这种资源比较简单,通过在程序中调用R.id.filenam e即可。
- assets目录下存放的原始资源文件,因为系统在编译的时候不会编译assets下的资源文件,所以我们不能通过R.id.filename的方式访问它们。那我么能不能通过该资源的绝对路径去访问它们呢?因为apk安装之后会放在/data/app/**.apk目录下,assets被绑定在apk里,以apk形式存在,并不会解压到/data/data/YourApp目录下去,所以我们无法直接获取到assets的绝对路径,因为它们根本就没有独立存在
res/raw和assets的相同点:
1.两者目录下的文件在打包后会原封不动的保存在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对象。Resources对象描述了android资源文件,例如android工程下的res、asset目录等除了.class文件的资源,我们可以认为,所有涉及到获取资源的地方,都可以使用Resources来获取。事实上我们在代码中读取asset目录下的资源时常常直接使用Assetmanager来直接获取对象的流数据,而AssetManager也是属于Resources对象的一个属性,都同时指向相同的对象。
Resources解析:
1.Resources对象的几个重要成员属性:
static Resources mSystem = null; // mSystem为一个静态的对象,代表了系统默认的资源管理。
final Object mAccessLock = new Object();
final Configuration mTmpConfig = new Configuration();
TypedValue mTmpValue = new TypedValue();
final AssetManager mAssets; // mAssets指向了系统默认的实例,mAsset的创建初始化过程是在C++层做的。
private final Configuration mConfiguration = new Configuration();
final DisplayMetrics mMetrics = new DisplayMetrics();
private NativePluralRules mPluralRule;
private Resources() {
mAssets = AssetManager.getSystem();
// NOTE: Intentionally leaving this uninitialized (all values set
// to zero), so that anyone who tries to do something that requires
// metrics will get a very wrong value.
mConfiguration.setToDefaults();
mMetrics.setToDefaults();
updateConfiguration(null, null);
mAssets.ensureStringBlocks();
}
我们在开发自己的应用时,是把自己需要的资源都放置到工程目录下的res文件夹下和asset文件夹下。当编译工程的时候,资源和源文件都将会打包到apk里面。运行应用的时候,Resources中AssetManager的路径默认指向了该apk的文件,如果是普通应用,一般apk文件被放置在data/app目录下,系统应用的apk包放在system/app下。
所以在启动应用的时候,Resources通过Assetmanager,AssetManager再根据设定的路径查找apk中的资源,就可以正确的找到自己的资源了。
既然AssetManager获取资源是根据指向的路径来完成,理论上我们改变AssetManager读取的路径,就可以指定加载自己的资源,事实上也是这样设计的。所以如果我们让AssetManager指向自己设定的Apk资源路径,就可以完成提取apk资源的目的了。 一些动态主题包的实现原理主要是通过AssetsManager.addAssetPath(String path) 这一接口来创建对应主题包的 Resources 对象来实现的。
Demo:
新建一个用于管理资源的类ResourcesManager,其中包含的重要属性与方法:
AssetManager mAssetManager = null;
Resources mResources = null;
LayoutInflater mLayoutInflater = null;
Theme mTheme = null;
ClassLoader mClassLoader = null;
//ResApk.apk 资源文件
String packageName = "com.example.testapk";
String libPath = Environment.getExternalStorageDirectory().toString()
+ File.separator + "ResApk.apk"; protected void initAssetManager() {
try {
AssetManager assetManager = AssetManager.class.newInstance();
Method addAssetPath = assetManager.getClass().getMethod(
"addAssetPath", String.class);
addAssetPath.invoke(assetManager, libPath);
mAssetManager = assetManager;
} catch (Exception e) {
e.printStackTrace();
}
Resources superRes = super.getResources();
mResources = new Resources(mAssetManager, superRes.getDisplayMetrics(),
superRes.getConfiguration());
}
mResources就指向了ResApk.apk里面的资源,通过名字就可以取得对应资源。
public int getDrawableId(String imgName) {
return mResources.getIdentifier(imgName, "drawable", apkPackageName);
}
/**
* 获取图片资源
*
* @param imgName
* @return drawable
*/
public Drawable getResApkDrawable(String imgName) {
return mResources.getDrawable(getDrawableId(imgName));
}
特别需要注意的是,由于每个应用的上下文对象都是不一样的,要始终记住,如果使用的不是自己资源文件,要慎用与上下文有关的功能方法。
原文参考博客链接:https://blog.csdn.net/MeteorLuoyidong/article/details/49530839
https://www.cnblogs.com/jpfss/p/9876370.html
Android资源管理利器Resources和AssetManager的更多相关文章
- 第14/15讲- Android资源管理
第14/15讲 Android资源管理 Android中的资源是指非代码部分,比如图片.MP3,字符串,XML文件等.在一个android工程中,res和assets是用来保存资源文件的. res和a ...
- (转载)android:android.content.res.Resources$NotFoundException: String resource ID #..
android.content.res.Resources$NotFoundException: String resource ID #0x0 找不到资源文件ID #0x0 原因分析如下: 遇到这种 ...
- android.content.res.Resources$NotFoundException:String resource ID #ffffffff
无语,搞了半天,只能去插这个错误代号,结果就找到了这个结果. scoreTextView.setText(score+""); 这个一定要自己手动转换..不科学啊..关键是在ecl ...
- android.content.res.Resources$NotFoundException: String resource ID #0x1
之前忘了记录这个错误,今天又遇到了.唉,人不能纵容自己犯懒,遂记录之. 错误:android.content.res.Resources$NotFoundException: String resou ...
- android错误之android.content.res.Resources$NotFoundException:
错误:android.content.res.Resources$NotFoundException: String resource ID #0x1 原因:一般发生在参数 int resId 错误, ...
- 调用android的getColor()方法出现 java.lang.NoSuchMethodError: android.content.res.Resources.getColor
1.java.lang.NoSuchMethodError: android.content.res.Resources.getDrawable/getColor或者 java.lang.NoSuch ...
- Android报“android.content.res.Resources$NotFoundException: String resource ID #0x2”错误
Android报“android.content.res.Resources$NotFoundException: String resource ID #0x2”错误 当调用setText()方法时 ...
- Caused by: android.content.res.Resources$NotFoundException: Resource ID #0x7f070058 android-studio 3.0 from canary 5 to canary 6
我升级android-studio到了3.0 canary 6打包编译安装出现如下错误: 07-11 13:00:39.523 8913-8913/dcpl.com.myapplication E/A ...
- 异常 android.content.res.Resources$NotFoundException: String resource ID #0x61
09-09 16:08:41.554: E/Weaver(13140):09-09 16:08:41.554: E/Weaver(13140): android.content.res.Resourc ...
随机推荐
- CodeForces 689 D Friends and Subsequences
Friends and Subsequences 题解: 如果左端点来说, 那么对于a[i]来说是向上的一条折线, b[i]来说是向下的一条折线, 那么如果这2个折线求交点个数的话, 我们可以二分去求 ...
- CodeForces 1083 E The Fair Nut and Rectangles 斜率优化DP
The Fair Nut and Rectangles 题意:有n个矩形,然后你可以选择k个矩形,选择一个矩形需要支付代价 ai, 问 总面积- 总支付代价 最大能是多少, 保证没有矩形套矩形. 题解 ...
- 模板汇总——AC自动机
AC自动机 模板题 HDU-2222 Keywords Search #include<bits/stdc++.h> using namespace std; #define LL lon ...
- happen before 原则
并发一直都是程序开发者绕不开的难题,在上一篇文章中我们知道了导致并发问题的源头是 : 多核 CPU 缓存导致程序的可见性问题.多线程间切换带来的原子性问题以及编译优化带来的顺序性问题. 原子性问题我们 ...
- html/css中float浮动的用法
一.float基础用法示例 1.我们先建两个div盒子,设置高度.宽度和背景颜色: 最开始两个盒子在网页上的位置如下: 然后我们将红色盒子浮动到右边 然后我们会发现红色盒子浮动到了右边,但是蓝色盒子就 ...
- 使用Nginx、Nginx Plus防止服务器DDoS攻击
分布式拒绝服务攻击(DDoS)指的是通过多台机器向一个服务或者网站发送大量看似合法的数据包使其网络阻塞.资源耗尽从而不能为正常用户提供正常服务的攻击手段.随着互联网带宽的增加和相关工具的不断发布,这种 ...
- spring组件注册
基于注解和类的组件注册 @Conditional 作用:按照一定的条件进行判断,如果满足条件的话就给spring容器中注册bean 该注解既可以标注到方法上面,也可以标注到类上面(只有满足条件时, ...
- 基于STM32F429的TFT0.96屏幕驱动
1.介绍TFT 2.Cube配置 该屏幕是用SPI通信的,但没有MISO引脚,意思是说该屏幕只能接收数据,但无法读取里面的数据,理论上说四线就能启动,但我弄不出,只能用六线. 在Cube上只要开启六 ...
- Android 网络通信框架Volley(二)
Volley提供2个静态方法: public static RequestQueue newRequestQueue(Context context) {} public static Request ...
- 去掉first li 的list图标
ul中,第一个 li 前的小图标,默认情况下为小圆点,在这种情况下,给 first li 设置 list-style-type: none;可以成功去除前面的小圆点的. 当给 li 设置了 list ...