美文网首页Android
通过 AssestManager 加载外部皮肤包

通过 AssestManager 加载外部皮肤包

作者: 石器时代小古董 | 来源:发表于2019-08-20 16:27 被阅读0次

    一、Android APK 中的资源文件

    在将程序打包成 APK 后,资源文件会单独打包成 resources.arsc 文件。它通过包名进行管理,通过ID,Name的方式通过 Resources 类进行加载。

    二、加载外部的资源包

    资源包实际上是一个 APK,它可以被 AssestManager进行加载,并通过 Resources 类加载其中的资源。

    三、资源文件如果被Resources类引用

    资源文件是通过 ID 被 Resources 引用到的。所以如果皮肤包中的资源和我们apk中原始的资源 ID 是一致的话,我们可以用通过这个ID在皮肤包的Resources中找到对应的资源,加载这个资源实现皮肤的替换

    四、加载外部资源

    1.外部资源可以通过AssestManager进行加载,所以首先需要创建一个AssestManager

    注意这里不能使用Application.getAssest(),这种方式获得AssetManager会少初始化很多东西

         AssetManager assetManager = AssetManager.class.newInstance();
    

    2.AssestManager加载皮肤包

    AssestManager通过addAssetPath的函数加载资源包,但这个函数本身是隐藏的,需要通过反射的方式加载

        Method addAssetPath = assetManager.getClass().getDeclaredMethod(ADD_ASSET_PATH, String.class);
        // 设置私有方法可访问
        addAssetPath.setAccessible(true);
        // 执行addAssetPath方法
        addAssetPath.invoke(assetManager, skinPath);
    

    3.读取皮肤包中的资源

    有了AssestManager后,就可以获取到 Resources 类了

    这里通过了apk已经准备好的资源类获取到了DsplayMetrics,Configuration 参数

     this.application = application;
            appResources = application.getResources();
    
     skinResources = new Resources(assetManager,
                        appResources.getDisplayMetrics(), appResources.getConfiguration());
    

    4.通过ID映射实际的资源

    需要找到皮肤包中对应的资源的 ID

     private int getSkinResourceIds(int resourceId) {
            if (isDefaultSkin) return resourceId;
    
            String resourceName = appResources.getResourceEntryName(resourceId);
            String resourceType = appResources.getResourceTypeName(resourceId);
    
            // 动态获取皮肤包内的指定资源ID
            // getResources().getIdentifier(“netease_bg”, “drawable”, “com.netease.skin.packages”);
            int skinResourceId = skinResources.getIdentifier(resourceName, resourceType, skinPackageName);
    
            isDefaultSkin = skinResourceId == 0;
            return skinResourceId == 0 ? resourceId : skinResourceId;
        }
    
    5.加载皮肤包的资源

    有了 ID 就可以加载皮肤包中的资源了,在需要换肤的时候通过这些通过使用皮肤包的 Resources 类加载其中的资源实现换肤

     public int getColor(int resourceId) {
            int ids = getSkinResourceIds(resourceId);
            return isDefaultSkin ? appResources.getColor(ids) : skinResources.getColor(ids);
        }
    
        public ColorStateList getColorStateList(int resourceId) {
            int ids = getSkinResourceIds(resourceId);
            return isDefaultSkin ? appResources.getColorStateList(ids) : skinResources.getColorStateList(ids);
        }
    
        // mipmap和drawable统一用法(待测)
        public Drawable getDrawableOrMipMap(int resourceId) {
            int ids = getSkinResourceIds(resourceId);
            return isDefaultSkin ? appResources.getDrawable(ids) : skinResources.getDrawable(ids);
        }
    
        public String getString(int resourceId) {
            int ids = getSkinResourceIds(resourceId);
            return isDefaultSkin ? appResources.getString(ids) : skinResources.getString(ids);
        }
    

    相关文章

      网友评论

        本文标题:通过 AssestManager 加载外部皮肤包

        本文链接:https://www.haomeiwen.com/subject/oxwpsctx.html