ImageView的src、TextView的textColor等资源加载源码

1. 概述


这节课我们来分析下Google是如何进行 资源加载的,比如我们直接在布局文件中写一个 ImageView,然后直接用 android:src="@mipmap/ic_launcher" 就能引入一张图片,到底是为什么,那么接下来我们就来看下, 系统到底是如何加载资源的,下边我们就以 ImageView里边的 src 为例,来进行源码分析,或者文字的textColor都是一样的,都是根据下边源码分析的。

2. 源码分析流程如下

2.1>:直接点击ImageView,进入源码,然后看下ImageView的第三个构造方法:

public ImageView(Context context, @Nullable AttributeSet attrs, int defStyleAttr,
            int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);

        initImageView();

        final TypedArray a = context.obtainStyledAttributes(
                attrs, R.styleable.ImageView, defStyleAttr, defStyleRes);

        final Drawable d = a.getDrawable(R.styleable.ImageView_src);
        if (d != null) {
            setImageDrawable(d);
        }

        mBaselineAlignBottom = a.getBoolean(R.styleable.ImageView_baselineAlignBottom, false);
        mBaseline = a.getDimensionPixelSize(R.styleable.ImageView_baseline, -1);

        setAdjustViewBounds(a.getBoolean(R.styleable.ImageView_adjustViewBounds, false));
        setMaxWidth(a.getDimensionPixelSize(R.styleable.ImageView_maxWidth, Integer.MAX_VALUE));
        setMaxHeight(a.getDimensionPixelSize(R.styleable.ImageView_maxHeight, Integer.MAX_VALUE));

        final int index = a.getInt(R.styleable.ImageView_scaleType, -1);
     
    }

从上边我们看到,解析ImageView的 src

final Drawable d = a.getDrawable(R.styleable.ImageView_src);

然后点击 getDrawable进去,进入 TypedArray源码 中,看到 getDrawable()方法如下:

@Nullable
    public Drawable getDrawable(@StyleableRes int index) {
        if (mRecycled) {
            throw new RuntimeException("Cannot make calls to a recycled instance!");
        }

        final TypedValue value = mValue;
        if (getValueAt(index*AssetManager.STYLE_NUM_ENTRIES, value)) {
            if (value.type == TypedValue.TYPE_ATTRIBUTE) {
                throw new UnsupportedOperationException(
                        "Failed to resolve attribute at index " + index + ": " + value);
            }
            return mResources.loadDrawable(value, value.resourceId, mTheme);
        }
        return null;
    }

可以看到,不管是解析图片资源ImageView、还是文字的 textColor资源,其实最终都是调用的

mResources.loadDrawable(value, value.resourceId, mTheme);

而这个 mResources 其实就是 Resource,也就是说资源加载都是通过 Resource对象去读取的。既然资源的加载都是通过 Resource类加载的,那么如果我想获取另外一个apk中的资源,是不是可以自己实例化一个Resource。
只要清楚是怎么去实例化 Rescource就好,也就是说是如何 new Rescource对象,下边可以看到源码中它也是直接 new Rescource对象的

r = new Resources(assets, dm, config, compatInfo);
// 这个是 点击Resources进去的 ,它的构造方法,参数1 assets表示  AssetManager资源管理
Resources(AssetManager assets, DisplayMetrics metrics, Configuration config)

在这里我们只需要搞清楚 AssetManager资源管理是怎么实例化的就ok,

@VisibleForTesting
    protected @Nullable AssetManager createAssetManager(@NonNull final ResourcesKey key) {


        AssetManager assets = new AssetManager();

        if (key.mResDir != null) {
            if (assets.addAssetPath(key.mResDir) == 0) {
                Log.e(TAG, "failed to add asset path " + key.mResDir);
                return null;
            }
        }
        }
        return assets;
    }

通过下边的方法可以知道,它是直接 new AssetManager的,同时也调用了
assets.addAssetPath(key.mResDir)方法,里边的 mResDir 就是 apk的目录

    /**
     * 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) {
        synchronized (this) {
            int res = addAssetPathNative(path, appAsLib);
            makeStringBlocks(mStringBlocks);
            return res;
        }
    }

通过以上分析,总结资源加载

所有的资源加载是通过 Resource ->
而Rescource是直接 new = new Resources(assets, dm, config, compatInfo);对象,参数assets是非常重要的 ->
AssetsManager,这个其实是 Resource的核心的实例 ->
其实最终获取资源是通过 AssetsManager获取的;

AssetsManager实例化如下,并且调用 addAssetPath(key.mResDir)方法,注意下边的key.mResDir可以是一个 ZIP路径,其实就是 apk的目录

AssetManager assets = new AssetManager();
assets.addAssetPath(key.mResDir)

以上就是 资源加载的源码分析,注意其实 .apk也是 .zip,都是一样的。

你可能感兴趣的:(ImageView的src、TextView的textColor等资源加载源码)