Android AssetManager 简读<2>

前面一篇大致介绍如何装载各种资源到系统路径下,下面看看如何获取这些资源.

做每一个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
















  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值