插件化:资源加载

本文详细介绍了在Android应用中如何实现插件化的资源加载过程。包括如何为插件APK创建独立的Resources对象,以及如何在宿主应用中提供插件资源的方法。通过重写Context的getResource方法,实现了插件APK能够正确地使用自身的资源。

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

参考:http://blog.youkuaiyun.com/yulong0809/article/details/59489396

插件化:加载资源
1、LoadedApk是一个apk在内存中的标示, Apk文件的相关信息,诸如Apk文件的代码和资源,甚至代码里面的Activity,Service等四大组件的信息我们都可以通过此对象获取;
2、LoadedApk 创建的时候会传入一个ApplicationInfo的对象,也就是说我们插件中使用的资源,其实用的是宿主的资源库,然而宿主的资源库并没有插件的资源,所以肯定会报错;
3、我们使用资源的时候,一般都是通过R.或者Context.getResources(),而R.也是通过Context.getResources()获取id的。看Context的视线类ContextImpl的源码
4、getResources()返回的是Resources对象:mResouces;看一下mResources是怎么创建的?
5、在ContextImpl的构造方法中创建了mResources,mResources是通过ResourcesManager创建的: mResources = mResourcesManager.getTopLevelResources()
6、ResourcesManager.getTopLevelResources()主要通过3步来得到Resources对象的:
a.创建AssetManager对象:AssetManager assets = new AssetManager();
b.通过assets.addAssetPath(resDir)方法给AssetManager添加资源路径;
c.通过AssetManager来创建一个Resources对象。

加载资源的思路:
1、给插件apk创建一个属于自己的Resources对象;
2、插件apk默认拿的是宿主的Resources对象,所以得在宿主中提供一个返回插件apk自己资源的方法;
3、在插件apk中我们要重写Context的getResource方法

总结:就是在宿主中构造好插件的资源,然后提供一个获取资源的方法,然后在插件中用资源的时候,掉用宿主提供的方法。

实现
都写在Application这个类中了:

public class MyApplication extends Application {
    private static Context sContext;

    private AssetManager assetManager;
    private Resources newResource;
    private Resources.Theme mTheme;

    @Override
    protected void attachBaseContext(Context base) {
        super.attachBaseContext(base);
        sContext = base;

        try {

            //创建我们自己的Resource
            //这是插件apk的路径
            String apkPath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/demo.apk";
            assetManager = AssetManager.class.newInstance();
            Method addAssetPathMethod = assetManager.getClass().getDeclaredMethod("addAssetPath", String.class);
            addAssetPathMethod.setAccessible(true);

            addAssetPathMethod.invoke(assetManager, apkPath);

            Method ensureStringBlocks = AssetManager.class.getDeclaredMethod("ensureStringBlocks");
            ensureStringBlocks.setAccessible(true);
            ensureStringBlocks.invoke(assetManager);

            Resources supResource = getResources();
            Log.e("Main", "supResource = " + supResource);
            newResource = new Resources(assetManager, supResource.getDisplayMetrics(), supResource.getConfiguration());
            Log.e("Main", "设置 getResource = " + getResources());

            mTheme = newResource.newTheme();
            mTheme.setTo(super.getTheme());
        } catch (Exception e) {
            Log.e("Main", "走了我的callActivityOnCreate 错了 = " + e.getMessage());
            e.printStackTrace();
        }

    }

    @Override
    public AssetManager getAssets() {
        return assetManager == null ? super.getAssets() : assetManager;
    }

    @Override
    public Resources getResources() {
        return newResource == null ? super.getResources() : newResource;
    }

    @Override
    public Resources.Theme getTheme() {
        return mTheme == null ? super.getTheme() : mTheme;
    }

    public static Context getContext() {
        return sContext;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值