android动态加载sd卡的xml布局文件

来源:互联网 发布:tensorflow pytorch 编辑:程序博客网 时间:2024/06/05 03:11

<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">app加载sdcard里面的布局文件</span>

在Android系统中可以使用

LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);v = inflater.inflate(R.layout.number_auto_roll, null);

来生成相应的布局, 但是layout文件必须在打包在apk中,如果发布后仍需要微调布局文件就要重新打包呢?

从v = inflater.inflate(R.layout.number_auto_roll, null);往下看, 发现调用的是View inflate(XmlPullParser parser, ViewGroup root, boolean attachToRoot) 这个方法,也是通过解析xml得出的布局文件。那我们是不是也可以通过解析xml文件的方式来创建相应的view。

第一次使用 

XmlPullParser parser = Xml.newPullParser();
parser.setInput(inStream, "UTF-8");
生成的XmlPullParser ,结果在inflate的时候,报错,不识别xml文件。然后发现在系统的inflate中有

    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();        }    }
原来系统使用的XmlResourceParser,而AssetManager.java中有一个方法是openXmlResourceParser,可以使用他来生成一个XmlResourceParser。

paser = assetManager.openXmlResourceParser(cookie,"number_auto_roll.xml"); 并且把number_auto_roll.xml放在assets目录下,但是每次都报错(FileNotFound);

后面仔细查看,调用的AssetManager.cpp中的openNonAsset -> openNonAssetInPathLocked,在openNonAssetInPathLocked有如下一段代码

    /* look at the filesystem on disk */    if (ap.type == kFileTypeDirectory) {        String8 path(ap.path);        path.appendPath(fileName);        pAsset = openAssetFromFileLocked(path, mode);        if (pAsset == NULL) {            /* try again, this time with ".gz" */            path.append(".gz");            pAsset = openAssetFromFileLocked(path, mode);        }        if (pAsset != NULL) {            //printf("FOUND NA '%s' on disk\n", fileName);            pAsset->setAssetSource(path);        }


就是说有个前缀路径,需要将我们的前缀加入进来才能读取都文件。
在AssetManager.java中有一个隐藏的方法
    /**     * 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 native final int addAssetPath(String path);
可以把我们的xml布局的路径加进来,另外由于openXmlResourceParser只能读取编译后的文件,我们先把编译后的number_auto_roll.xml放在了/sdcard/abcdefg/目录下。下面是相应的代码
private XmlPullParser getLayoutXmlPullParser() {XmlResourceParser paser = null;try {AssetManager asset = getResources().getAssets();Class<AssetManager> c = AssetManager.class;try {Method method= c.getMethod("addAssetPath",String.class);try {int cookie = (Integer) method.invoke(asset, "/sdcard/abcdefg/");paser = asset.openXmlResourceParser(cookie,"number_auto_roll.xml");} catch (IllegalArgumentException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (IllegalAccessException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (InvocationTargetException e) {// TODO Auto-generated catch blocke.printStackTrace();}} catch (NoSuchMethodException e) {// TODO Auto-generated catch blocke.printStackTrace();}} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}return paser;//XmlPullParser paser  = Xml.newPullParser();//try {//paser.setInput(getResources().getAssets().open("number_auto_roll.xml"),"UTF-8");//} catch (XmlPullParserException e1) {//// TODO Auto-generated catch block//e1.printStackTrace();//} catch (IOException e1) {//// TODO Auto-generated catch block//e1.printStackTrace();//}//return paser;//try {//return getResources().getAssets().openXmlResourceParser(//"number_auto_roll.xml");//} catch (IOException e) {//// TODO Auto-generated catch block//e.printStackTrace();//return null;//}}
<pre name="code" class="java">private void init(Context context) {mContext = context;LayoutInflater inflater = (LayoutInflater) mContext.getSystemService(Context.LAYOUT_INFLATER_SERVICE);XmlPullParser paser = getLayoutXmlPullParser();View v;if (paser != null) {v = inflater.inflate(paser, this, true);} else {v = inflater.inflate(R.layout.number_auto_roll, null);addView(v);}
}



0 0
原创粉丝点击