资源管理机制
来源:互联网 发布:手机sdr软件无线电 编辑:程序博客网 时间:2024/05/11 16:21
想要获取资源最关键的是把APK中的资源转为Resources对象。
然后根据不同的资源类型调用Resources对象的对应的方法,比如getString获得字符串资源
在一个Acitvity或者一个Service中,我们可以直接调用getResources()方法,就可以获得Reousrces对象。因为Acitivity或者Service本质上就是一个Context,getResources()方法是Context中的抽象的方法,而真正的实现是在ContextImpl类,所以调用的实际上是ContextImpl类的getResources()方法。
Context继承关系
Context 里面有一个mBase的对象,指向的是ContextImpl的实例
ContextImpl源码分析
在ContextImpl类中有一个成员
private Resources mResources,它就是getResources方法返回的结果,
mResources的赋值代码为:
// 第一个参数是apk的路径,第二个参数应该是屏幕分辨率。
mResources = mResourcesManager.getTopLevelResources(mPackageInfo.getResDir(),
Display.DEFAULT_DISPLAY, null, compatInfo, activityToken);
这个方法的思想是这样的:
因为res下可能存在多个适配不同设备、不同分辨率、不同系统版本的目录,按照Android系统的设计,不同的参数在访问同一个应用的时候访问的资源可以不同,比如drawable-hdpi和drawable-xhdpi就是对应2个资源。所有的资源对象都被存储在mActiveResources中,mActiveResources对象内部保存了该应用程序所使用到的所有Resources对象,其类型为Hash<ResourcesKey,WeakReference<Resourcces>>,可以看出这些Resources对象都是以一个弱引用的方式保存,以便在内存紧张时可以释放Resources所占内存。
首先根据当前的设备请求参数屏幕分辨率,横竖屏等去hash里查找对应的资源,如果找到了就返回,
否则就创建一个对应的资源对象保存到mActiveResources中。
- public Resources getTopLevelResources(String resDir, int displayId,
- Configuration overrideConfiguration, CompatibilityInfo compatInfo, IBinder token) {
- final float scale = compatInfo.applicationScale;
- // 根据参数获取对应的ResourcesKey,不同分辨率对应不同的ResourcesKey
- ResourcesKey key = new ResourcesKey(resDir, displayId, overrideConfiguration, scale,
- token);
- Resources r;
- synchronized (this) {
-
// 根据ResourcesKey获取对应的Resources对象,找到了就直接返回 - WeakReference<Resources> wr = mActiveResources.get(key);
- r = wr != null ? wr.get() : null;
- if (r != null && r.getAssets().isUpToDate()) {
- if (false) {
-
- }
- return r;
- }
- }
-
- // 如果没有对应的Resources对象,则生成对应的Resources对象
- // 创建Resources对象需要先创建AssetManager对象,动态加载里有介绍。
- AssetManager assets = new AssetManager();
- if (assets.addAssetPath(resDir) == 0) {
- return null;
- }
- DisplayMetrics dm = getDisplayMetricsLocked(displayId);
- Configuration config;
- boolean isDefaultDisplay = (displayId == Display.DEFAULT_DISPLAY);
- final boolean hasOverrideConfig = key.hasOverrideConfiguration();
- if (!isDefaultDisplay || hasOverrideConfig) {
- config = new Configuration(getConfiguration());
- if (!isDefaultDisplay) {
- applyNonDefaultDisplayMetricsToConfigurationLocked(dm, config);
- }
- if (hasOverrideConfig) {
- config.updateFrom(key.mOverrideConfiguration);
- }
- } else {
- config = getConfiguration();
- }
- r = new Resources(assets, dm, config, compatInfo, token);
- if (false) {
-
- }
- synchronized (this) {
- // 把创建的Resources对象保存到hash中以便以后直接使用
- WeakReference<Resources> wr = mActiveResources.get(key);
- Resources existing = wr != null ? wr.get() : null;
- if (existing != null && existing.getAssets().isUpToDate()) {
-
- r.getAssets().close();
- return existing;
- }
- // XXX need to remove entries when weak references go away
- mActiveResources.put(key, new WeakReference<Resources>(r));
- return r;
- }
- }
再看下ResourcesManager类的实现:
单例模式的ResourcesManager类
- public static ResourcesManager getInstance() {
- synchronized (ResourcesManager.class) {
- if (sResourcesManager == null) {
- sResourcesManager = new ResourcesManager();
- }
- return sResourcesManager;
- }
- }
Resources对象的创建
动态加载中介绍过,根据构造函数public Resources(AssetManager assets, DisplayMetrics metrics, Configuration config)
我们需要先构造一个AssetManager对象
可以看到上面源码中的构造如下:
- AssetManager assets = new AssetManager();
- if (assets.addAssetPath(resDir) == 0) {
- return null;
- }
为什么这里不是用的反射呢?动态加载中是用的反射
看下addAssetPath函数的定义
- /**
- * Add an additional set of assets to the asset manager. This can be
- * either a directory or ZIP file. Not for use by applications. Returns
- * the cookie of the added asset, or 0 on failure.
- * {@hide}
- */
- public final int addAssetPath(String path) {
- int res = addAssetPathNative(path);
- return res;
- }
注意到它的注释里面有一个{@hide}关键字,这意味着即使它是public的,但是外界仍然无法访问它,因为android sdk导出的时候会自动忽略隐藏的api,因此只能通过反射来调用。可见sdk导出的时候才不能直接使用这个api,那么在sdk里面是可以直接使用的。
- 资源管理机制
- unity3d引擎的资源管理机制
- c#资源管理和垃圾回收机制
- Android中资源管理机制详细分析
- 浅析游戏引擎的资源管理机制
- Android中资源管理机制详细分析
- 浅析游戏引擎的资源管理机制
- 浅析游戏引擎的资源管理机制
- Android中资源管理机制详细分析
- Android中资源管理机制详细分析
- 资源管理
- 资源管理
- 资源管理
- 资源管理
- 资源管理
- 资源管理
- 资源管理
- 资源管理
- v4.DialogFragment设置宽高
- Eclipse控制台中的中文输出乱码问题
- 安装virtualbox时安装程序出现严重错误
- PostgreSQL数据库远程连接配置
- Xenserver主节点故障处理示例/Xenserver进入单用户
- 资源管理机制
- swfupload文件删除
- sql server作业中各列的含义
- CRM开发要点(六)
- XenServer下一个SR异常处理—记录篇
- linux常用命令
- swfload文件下载
- Ibtis和Mybatis多参数查询之list集合查询
- CSS选择器