Android AssetManager 簡讀

前面一篇大致介紹如何裝載各種資源到系統路徑下,下面看看如何獲取這些資源.

做每一個Activity時,不可或缺的需要設置一個佈局,後者一個View來顯示給用戶.

public void setContentView(int layoutResID)

以及:

public void setContentView(View view)

都比較常見.

先看第一種:

public void setContentView(int layoutResID) {
        getWindow().setContentView(layoutResID);
        initActionBar();
    }

程序的通過getWindow...直接將資源ID交給了Window類去處理,後面的initActivityBar在Activity創建的時候就獲取的Actionbar的樣式,參考前面的Activity圖形化生成的博文.下面繼續看看Window是如何處理資源的:打開PhoneWindow.java

@Override
    public void setContentView(int layoutResID) {
        if (mContentParent == null) {
            installDecor();
        } else {
            mContentParent.removeAllViews();
        }
        mLayoutInflater.inflate(layoutResID, mContentParent);
        final Callback cb = getCallback();
        if (cb != null && !isDestroyed()) {
            cb.onContentChanged();
        }
    }

一看,和前面Activity的圖形化生成有的一拼,這個地方我們只關注資源是如何解析獲取的.

mLayoutInflater.inflate(layoutResID, mContentParent);

這個就是LayoutInflater類,這個類應該很熟悉,經常在一些彈出框界面顯示View的時候使用.

轉到LayoutInflate類中:

public View inflate(int resource, ViewGroup root, boolean attachToRoot) {
        if (DEBUG) System.out.println("INFLATING from resource: " + resource);
        XmlResourceParser parser = getContext().getResources().getLayout(resource);
        try {
            return inflate(parser, root, attachToRoot);
        } finally {
            parser.close();
        }
    }

這裏面不再去介紹上面方法中的inflate(....)是如何將各自的view添加到root中了.

只看資源解析:

XmlResourceParser parser = getContext().getResources().getLayout(resource);

然後繼續跟蹤:

public XmlResourceParser getLayout(int id) throws NotFoundException {
        return loadXmlResourceParser(id, "layout");
    }

就到了Resource.java類中:

/*package*/ XmlResourceParser loadXmlResourceParser(int id, String type)
            throws NotFoundException {
        synchronized (mTmpValue) {
            TypedValue value = mTmpValue;
            getValue(id, value, true);
            if (value.type == TypedValue.TYPE_STRING) {
                return loadXmlResourceParser(value.string.toString(), id,
                        value.assetCookie, type);
            }
            throw new NotFoundException(
                    "Resource ID #0x" + Integer.toHexString(id) + " type #0x"
                    + Integer.toHexString(value.type) + " is not valid");
        }
    }


繼續看getValue方法:

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

看到mAssets.getResourceValue,就到了AssetManager管理器了,到jni層,跳過一些過度的類,這個類就跳過,直接看ResourceType.cpp

ssize_t ResTable::getResource(uint32_t resID, Res_value* outValue, bool mayBeBag, uint16_t density,
        uint32_t* outSpecFlags, ResTable_config* outConfig)

在這個方法裏面,都是由下面這一句展開的.這個地方或

const ssize_t p = getResourcePackageIndex(resID);

然後根據這個得到:

const PackageGroup* const grp = mPackageGroups[p];

獲取grp對象後,由於每一個package都對應一個PackageGroup,輪詢查找,通過ResourceIDmap獲取對應的資源rc返回.


這裏面涉及的資源結構體還是相當複雜,雖然很燒腦子,還好還是有牛人給出了具體說明,可以參考下面:

http://blog.csdn.net/luoshengyang/article/details/8744683
















發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章