ImageView的src、TextView的textColor等資源加載源碼

1. 概述


這節(jié)課我們來(lái)分析下Google是如何進(jìn)行 資源加載的,比如我們直接在布局文件中寫(xiě)一個(gè) ImageView,然后直接用 android:src="@mipmap/ic_launcher" 就能引入一張圖片,到底是為什么,那么接下來(lái)我們就來(lái)看下, 系統(tǒng)到底是如何加載資源的,下邊我們就以 ImageView里邊的 src 為例,來(lái)進(jìn)行源碼分析,或者文字的textColor都是一樣的,都是根據(jù)下邊源碼分析的。

2. 源碼分析流程如下

2.1>:直接點(diǎn)擊ImageView,進(jìn)入源碼,然后看下ImageView的第三個(gè)構(gòu)造方法:

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);

然后點(diǎn)擊 getDrawable進(jìn)去,進(jìn)入 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資源,其實(shí)最終都是調(diào)用的

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

而這個(gè) mResources 其實(shí)就是 Resource,也就是說(shuō)資源加載都是通過(guò) Resource對(duì)象去讀取的。既然資源的加載都是通過(guò) Resource類(lèi)加載的,那么如果我想獲取另外一個(gè)apk中的資源,是不是可以自己實(shí)例化一個(gè)Resource。
只要清楚是怎么去實(shí)例化 Rescource就好,也就是說(shuō)是如何 new Rescource對(duì)象,下邊可以看到源碼中它也是直接 new Rescource對(duì)象的

r = new Resources(assets, dm, config, compatInfo);
// 這個(gè)是 點(diǎn)擊Resources進(jìn)去的 ,它的構(gòu)造方法,參數(shù)1 assets表示  AssetManager資源管理
Resources(AssetManager assets, DisplayMetrics metrics, Configuration config)

在這里我們只需要搞清楚 AssetManager資源管理是怎么實(shí)例化的就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;
    }

通過(guò)下邊的方法可以知道,它是直接 new AssetManager的,同時(shí)也調(diào)用了
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;
        }
    }

通過(guò)以上分析,總結(jié)資源加載

所有的資源加載是通過(guò) Resource ->
而Rescource是直接 new = new Resources(assets, dm, config, compatInfo);對(duì)象,參數(shù)assets是非常重要的 ->
AssetsManager,這個(gè)其實(shí)是 Resource的核心的實(shí)例 ->
其實(shí)最終獲取資源是通過(guò) AssetsManager獲取的;

AssetsManager實(shí)例化如下,并且調(diào)用 addAssetPath(key.mResDir)方法,注意下邊的key.mResDir可以是一個(gè) ZIP路徑,其實(shí)就是 apk的目錄

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

以上就是 資源加載的源碼分析,注意其實(shí) .apk也是 .zip,都是一樣的。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容