如何创建一个LayoutInflater,给定XmlPullParser作为输入?

4

我有一个包含String Format的Layout.xml的字符串输入。

 // String that contains the Layout.xml :

 String concat ;

 // Create the XmlPullParser from the String format

 XmlPullParserFactory factory = XmlPullParserFactory.newInstance();

 factory.setNamespaceAware(true);

 XmlPullParser xpp = factory.newPullParser();
 xpp.setInput( new StringReader (concat) ); 

 // create le The LayoutInflater 

 LayoutInflater inflater =         (LayoutInflater)this.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

 View myView = inflater.inflate(xpp, null);

我遇到了这个bug:

03-12 08:23:12.876: W/System.err(937): android.view.InflateException: START_TAG http://schemas.android.com/apk/res/android}android:orientation='vertical' {http://schemas.android.com/apk/res/android}android:layout_width='fill_parent' {http://schemas.android.com/apk/res/android}android:layout_height='fill_parent'>@1:226 in java.io.StringReader@44f50508: Error inflating class

请帮忙解决一下?
1个回答

3
似乎Inflater只接受XmlBlock。我编写了一个方法来实现此功能,你可以参考该项目网站:https://github.com/liudongmiao/preference-fragment-compat/blob/master/src/me/piebridge/android/preference/PreferenceFragment.java#L202。主要代码如下:
// byte[] data = ... 
// bytes of compiled xml (unzip the apk, get the bytes from res/layout*/*.xml)

// XmlBlock block = new XmlBlock(data);
Class<?> clazz = Class.forName("android.content.res.XmlBlock");
Constructor<?> constructor = clazz.getDeclaredConstructor(byte[].class);
constructor.setAccessible(true);
Object block = constructor.newInstance(data);

// XmlPullParser parser = block.newParser();
Method method = clazz.getDeclaredMethod("newParser");
method.setAccessible(true);
XmlPullParser parser = method.invoke(block);

我正试图在你的仓库中使用 PreferenceFragment.getParser(String xml) 方法。我看到你将 public static final String LAYOUT 传递给了你的 getParser() 方法,并将 LAYOUT 作为 View 填充。你是如何生成 String LAYOUT 的?我猜测你以某种方式编码了你的布局的已编译代码,但我想知道细节,以便我可以将自己的布局编码成与你为 LAYOUT 所做的相同格式...? - Wess
1
@Wess 我已经在评论中写了,请再读一遍。 - liudongmiao
谢谢@liudongmiao。我按照您的步骤进行了操作,但是我总是得到“NullPointerException: Attempt to invoke interface method 'java.lang.String org.xmlpull.v1.XmlPullParser.getPositionDescription()' on a null object reference”的错误提示。我的步骤是:解压apk -> 将编译后的布局复制到项目的res/raw目录下 -> 在运行时读取布局文件内容并将其转换为字符串 -> 将字符串转换为byte[] data并传递给Object block = constructor.newInstance(data);。不确定我做错了什么?任何帮助将不胜感激。 - Wess
我实现了你的代码,但在运行时出现了InvocationTargetException异常。在异常上面的日志中,我看到了一行关于XmlBlock的内容: Bad XML block: header size 28024 or total size 1702240364 is larger than data size 2757 - SamiAzar
@liudongmiao - 如果你能回答上面评论区用户的问题那就太好了。我觉得你的方法很有意思,但是我还没有尝试过。这种方法仍然有效吗?预编译XML文件生成的二进制代码是否包含每个视图的预分配ID?如果是,则在将此布局膨胀到另一个视图时可能会与现有ID发生冲突。你是否可以提供更多关于二进制数据、使用方法和限制方面的信息呢?谢谢! - Ωmega

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接