Atlas框架源码简要分析(下)--Bundle资源处理

本文深入剖析了Atlas框架中Bundle资源处理的细节,包括如何将Bundle资源路径添加到系统资源查找路径,处理不同SDK版本的资源查找策略,以及AssetManager和Resource的更新。重点介绍了addAssetPathNative()方法的使用,以及在不同API级别下资源路径的添加和AssetManager的更新逻辑。文章详细阐述了资源处理的完整流程,为理解Atlas框架提供了宝贵参考。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Atlas框架源码简要分析(下)–Bundle资源处理

在上文中以启动一个在没有安装的Bundle中的Activity为例,整理了整个Bundle安装到该Activity对象实例化出来的过程,当该Bundle安装之后,对应的BundleClassLoader实例化完成之后,在<中>2.10.2处会对Bundle中的资源进行处理。我们下面就对资源的处理步骤详细展开

对于系统对资源的管理可以参考:http://blog.csdn.net/luoshengyang/article/details/8738877

1.1 重新贴出Bundle资源处理的入口代码如下:
1.1.1 此处为Bundle中资源处理的入口点,处理的根本思路就是想办法把该Bundle安装位置信息(即资源路径)添加到系统的资源查找路径列表中去

DelegateResources.addBundleResources()中第一个参数是,当前Bundle当前版本解压之后所在的位置,也就是资源文件所在的位置,第二个参数是Patch文件的位置。

@BundleLifecycleHandler.java
private void loaded(Bundle bundle) {//在BundleImpl建立之后,此时bundle解压的位置,及其中的ClassLoader已经初始化完毕,则会发送CMD=0的指令到达bundleChanged,进而调用此处开始:资源加载起始点
    BundleImpl b = (BundleImpl) bundle;

    try {
          DelegateResources.addBundleResources(b.getArchive().getArchiveFile().getAbsolutePath(),
                  b.getArchive().getCurrentRevision().getDebugPatchFilePath());//-------1.1.1 DelegateResources的addBundleResource(),添加当前bundle的资源到系统中去
    } catch (Exception e) {
        e.printStackTrace();
    }
}
.....//省略代码
}
1.2 调用DelegateResources添加当前bundle中的资源到系统中,具体代码和简要逻辑如下,(此处的debug资源也包括更新的patch资源)
@DelegateResource.java
//代理资源类,该方法相当于一个工具方法,此处的RuntimeVariables.delegateResources 是在Atlas启动之后即赋值的最初默认值为主bundle的Resource
public static void addBundleResources(String assetPath,String debugPath)  throws Exception{
    synchronized (DelegateResources.class) {
        if(debugPath!=null && !findResByAssetIndexDescending()){//------1.2.1此处主要兼容SDK20的查找方式不同,以确定debug包中的资源是否在实际资源之前加载
            updateResources(RuntimeVariables.delegateResources, debugPath, BUNDLE_RES);

        }
        updateResources(RuntimeVariables.delegateResources, assetPath, BUNDLE_RES);//------1.2.2更新一开始一同默认的resource,主要是把当前bundle的资源路径,通过反射添加到原有resource的路径上去,**各bundle在打包时,资源对应的id是打包为一个R文件的,里面记录的是对应资源的序列号,此处需要再看怎么根据这个号找到具体位置的**
        if(debugPath!=null && findResByAssetIndexDescending()){//------1.2.3 添加debug资源的路径
            updateResources(RuntimeVariables.delegateResources, debugPath, BUNDLE_RES);

        }
    }
}   
1.2.1 处主要兼容SDK20的资源查找方式不同,以确定debug包中的资源是否在实际资源之前加载

在SDK>20版本中资源查找的方式是按照资源路径列表降序查找的,也就是说后加入的路径会先去查找,而我们的debug资源目的是想要后查找,即先去正常资源中查找然后没有再到debug的资源中去查找,所以在SDK>20的版本中即findResByAssetIndexDescending()为true时就先执行跳过该步骤,先执行1.2.2添加正常的资源路径,否则就先执行此处代码添加debug的资源

  • 总之就是保证在查找资源时先从该Bundle的正常资源路径中找然后再到debug的资源路径中去查找
1.2.2 处理我们bundle的资源路径
  • 该处的RuntimeVariables.delegateResources 是在Atlas启动之后即赋值的最初默认值为主bundle的Resource,也就是系统生成的那一份resource,显然该使用该resource,我们是找不到bundle中的资源的,应为其默认的搜索路径是apk安装包位置

  • 该处的assetPath就是我们前面传入的b.getArchive().getArchiveFile().getAbsolutePath()即当前bundle解压之后的路径

1.2.3 此处和1.2.1处对应如果1.2.1处不执行则在此处执行debug中的资源处理
1.3 bundle资源更新处理,接上面1.2.2处逻辑,该处及最终处理资源的逻辑,分别处理了Resource中的AssetManager,然后处理Resource。展开其逻辑及代码如下
@DelegateResource.java
private static void updateResources(Resources res,String assetPath,int assertType) throws Exception{//更新当前Resource中资源路径集合,把新加入的bundle资源路径添加进去
    if(sAssetManagerProcessor==null){
        sAssetManagerProcessor = new AssetManagerProcessor();//-------1.3.1DelegateResource 的内部类里面有自己保存的一份资源列表
    }
    AssetManager updatedAssetManager = sAssetManagerProcessor.updateAssetManager(res.getAssets(), assetPath, assertType);//-------1.3.2更新AssetManager,此处只是更新AssetManager,然后我们需要把代理过的新的Manager重新给放入到Resource中去

    if(sResourcesProcessor==null){
        sResourcesProcessor = getResourceProcessor();//------1.3.3拿取ResourceProcessor
    }
    sResourcesProcessor.updateResources(updatedAssetManager);//-------1.3.4更新Resource中的AssetsManager为我们代理的AssetsManager

    if(sResourcesFetcher==null){
        sResourcesFetcher = new ResourceIdFetcher();
    }
}
1.3.1 如果sAssetManagerProcessor为null则初始化AssetManagerProcessor,该类来处理系统当前的AssetManager,初始化代码如下:
@AssetManagerProcessor.java
private static class AssetManagerProcessor {

    private static HashMap<String,Boolean> sDefaultAssetPathList  ;
    static {
        try {
            AssetManager manager = AssetManager.class.newInstance();
            ArrayList<String> defaultPaths = getAssetPath(manager);
            if(defaultPaths!=null && defaultPaths.size()>0){
                sDefaultAssetPathList = new HashMap<String,Boolean>();
                for(String path : defaultPaths){
                    sDefaultAssetPathList.put(path,Boolean.FALSE);
                }
            }
        }catch (Throwable e){}finally {
            if(sDefaultAssetPathList==null){
                sDefaultAssetPathList = new HashMap<String,Boolean>(0);
            }
        }
    }
    private LinkedHashMap<String,Boolean> assetPathCache = null;
    private LinkedHashMap<String,Boolean> preAssetPathCache = null;

    public AssetManagerProcessor(){
        assetPathCache = new LinkedHashMap<String,Boolean>();
        preAssetPat
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值