Android插件化原理(三)——加载插件资源


系列帖子:

Android插件化原理(一)—— 插件类加载、类加载原理、(双亲委托机制)
Android插件化原理(二)—启动插件Activity

应用

单作为一个技术点来讲,其实没有什么意义,还是要围绕需求展开的,加载插件资源最常见的应用就是插件化换肤了。我们直到,apk绝大部分体积都是资源,如果多套主题皮肤,那么包体积就会增加很多,
所以插件化换肤就很实用。可以实现多样化主题,个性化定制,提高了应用的灵活性和扩展性。

应用加载资源的原理

要看加载资源的原理,我们先看一下,在实际运行中如何获取资源的

如何获取资源

Activity

    protected void onCreate(Bundle savedInstanceState) {
   
   
        super.onCreate(savedInstanceState);
        getResources().getDrawable();
        getDrawable(0);
    }

Context

    @Nullable
    public final Drawable getDrawable(@DrawableRes int id) {
   
   
        return getResources().getDrawable(id, getTheme());
    }

实际上,不论是直接调用getDrawable或者Resource().getDrawable(),亦或者getContext().getDrawable()最终调用的都是Re
Resources的方法

Resources


    public Drawable getDrawable(@DrawableRes int id, @Nullable Theme theme)
            throws NotFoundException {
   
   
        return getDrawableForDensity(id, 0, theme);
    }

    @Nullable
    public Drawable getDrawableForDensity(@DrawableRes int id, int density, @Nullable Theme theme) {
   
   
        final TypedValue value = obtainTempTypedValue();
        try {
   
   
            final ResourcesImpl impl = mResourcesImpl;
            impl.getValueForDensity(id, density, value, true);
            return impl.loadDrawable(this, value, id, density, theme);
        } finally {
   
   
            releaseTempTypedValue(value);
        }
    }

    

ResourcesImpl

    void getValueForDensity(@AnyRes int id, int density, TypedValue outValue,
            boolean resolveRefs) throws NotFoundException {
   
   
        boolean found = mAssets.getResourceValue(id, density, outValue, resolveRefs);
        if (found) {
   
   
            return;
        }
        throw new NotFoundException("Resource ID #0x" + Integer.toHexString(id));
    }

其中,最重要的就是 mAssets.getResourceValue(id, density, outValue, resolveRefs),而mAssets就是android.content.res.AssetManager,

AssetManager


    boolean getResourceValue(@AnyRes int resId, int densityDpi, @NonNull TypedValue outValue,
            boolean resolveRefs) {
   
   
        Preconditions.checkNotNull(outValue, "outValue");
        synchronized (this) {
   
   
            ensureValidLocked();
            final int cookie = nativeGetResourceValue(
                    mObject, resId, (short) densityDpi, outValue, resolveRefs);
            if (cookie <= 0) {
   
   
                return false;
            }

            // Convert the changing configurations flags populated by native code.
            outValue.changingConfigurations = ActivityInfo.activityInfoConfigNativeToJava(
                    outValue.changingConfigurations);

            if (outValue.type == TypedValue.TYPE_STRING) {
   
   
                outValue.string = mApkAssets[cookie - 1].getStringFromPool(outValue.data);
            }
            return true;
        }
    }

    private static native int nativeGetResourceValue(long ptr, @AnyRes int resId, short density,
                                                     @NonNull TypedValue outValue, boolean resolveReferences);

最终呢,调用到了nativeGetResourceValue

总结:查找资源从Context开始到Context内部的Resources,再到Resources的成员ResourcesImpl,再到ResourcesImpl的成员AssetManager,最终呢,到大native层,到这一步,我们可以说资源实际上是由AssetManager管理的。
那么,AssetManager又是如何来的呢?

继续往下看应用资源加载原理

android资源加载原理

我们从Activity的创建开始,一步步看他的资源是如何加载出来的

ActivityThread.handleLaunchActivity

    @Override
    public Activity handleLaunchActivity(ActivityClientRecord r,
            PendingTransactionActions pendingActions, Intent customIntent) {
   
   
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值