我必须在Android上阅读大约约4000行的XML文件。首先我尝试SimpleXML library,因为它是最简单的,我的HTC Desire花了大约2分钟。所以我想也许SimpleXML因为反射和这个库使用的所有其他魔法而变得如此之慢。我重写了我的解析器并使用了内置的DOM解析方法,并对性能有一些特别的关注。这有点帮助,但它仍然需要大约60秒,这仍然是完全不可接受的。经过一番研究后,我找到了this article on developer.com。有一些图表显示其他两种可用方法 - SAX解析器和Android的XML Pull-Parser - 同样很慢。在文章的最后,您将找到以下声明:
我的第一个惊喜是这三种方法的速度有多慢。用户 不想在手机上等待很长时间,所以解析 任何超过几十条记录都可能要求采用不同的方法。
什么可能是“不同的方法”?如果你有超过“几十条记录”怎么办?
答案 0 :(得分:34)
(注意:请务必阅读下面的2016年更新!)
我刚刚对Android(和其他平台)上的解析器进行了一些性能测试。正在解析的XML文件只有500行左右(它是一个Twitter搜索Atom提要),但Pull和DOM解析可以在Samsung Galaxy S2或Motorola Xoom2上每秒大约翻译5个这样的文档。 OP中使用的SimpleXML(图表中的粉红色)与DOM解析最慢。
SAX解析在我的两个Android设备上的数量级更快,管理40个docs / sec单线程和65 + / sec多线程。
Android 2.3.4:
在Android 4.4.4和Android 6.0.1之间,情况发生了巨大变化,我们有了一个新的赢家:拉动解析FTW的速度是SAX吞吐量的两倍多。不幸的是,由于我没有运行Android>的任何设备,因此我不确切知道此更改的确切时间。 4.4.4和< 6.0.1。
Android 4.1.2:
Android 4.4.4:
Android 6.0.1:
答案 1 :(得分:5)
我认为在Android上使用XML的最佳方法是使用VDT-XML library
我的XML文件包含超过60 000行,VDT-XML处理如下:
Nexus 5:2055毫秒
Galaxy Note 4:2498 milisec
您可以通过链接找到更多基准报告:VTD-XML Benchmark
XML文件的简短示例
<database name="products">
<table name="category">
<column name="catId">20</column>
<column name="catName">Fruit</column>
</table>
<table name="category">
<column name="catId">31</column>
<column name="catName">Vegetables</column>
</table>
<table name="category">
<column name="catId">45</column>
<column name="catName">Rice</column>
</table>
<table name="category">
<column name="catId">50</column>
<column name="catName">Potatoes</column>
</table>
</database>
“build.gradle”文件的配置
dependencies {
compile files('libs/vtd-xml.jar')
}
源代码示例:
import com.ximpleware.AutoPilot;
import com.ximpleware.VTDGen;
import com.ximpleware.VTDNav;
String fileName = "products.xml";
VTDGen vg = new VTDGen();
if (vg.parseFile(fileName, true)) {
VTDNav vn = vg.getNav();
AutoPilot table = new AutoPilot(vn);
table.selectXPath("database/table");
while (table.iterate()) {
String tableName = vn.toString(vn.getAttrVal("name"));
if (tableName.equals("category")) {
AutoPilot column = new AutoPilot(vn);
column.selectElement("column");
while (column.iterate()) {
String text = vn.toNormalizedString(vn.getText());
String name = vn.toString(vn.getAttrVal("name"));
if (name.equals("catId")) {
Log.d("Category ID = " + text);
} else if (name.equals("catName")) {
Log.d("Category Name = " + text);
}
}
}
}
}
结果
Category ID = 20
Category Name = Fruit
Category ID = 31
Category Name = Vegetables
Category ID = 45
Category Name = Rice
Category ID = 50
Category Name = Potatoes
它对我有用,希望对你有所帮助。
答案 2 :(得分:0)
使用SAX解析器,我可以在HTC Desire上大约10秒内解析一个15,000行的XML文件。我怀疑还有其他一些问题。
您是否从XML填充数据库?如果是这样,您是否记得将整个解析操作包装在数据库事务中?仅这一点就可以将事情提高一个数量级。
答案 3 :(得分:0)
如果要解析XML中的日期,这会严重降低解析速度。随着Android的更新版本,这变得不那么成问题(因为他们优化了时区信息的加载)
如果你有正在解析的日期并且你不需要它们,那么你可以使用SAX解析器并忽略任何Date元素。
或者,如果您可以更改XML架构,请考虑将日期存储为整数而不是格式化字符串。
你提到你正在进行字符串比较,这也可能非常昂贵。也许考虑对你要比较的字符串使用HashMap,这可以提供显着的性能优势。
答案 4 :(得分:0)
很难告诉你为什么你的代码在没有看到你的代码的情况下很慢,并且当你没有提供任何测量的详细信息来证明这一点时,很难相信你的断言是因为XML解析器的缓慢。
答案 5 :(得分:0)
我们对1MB XML文件非常有效地使用了拉解析器 - 并且在我的欲望中大约10-20秒读取它们。所以,如果您的代码没问题,速度也会如此。显然DOM在有限的内存环境中非常慢,但是拉或SAX确实不是
答案 6 :(得分:0)
如果从Socket解析它的I / O花费时间,而不是解析。尝试首先使用数据,然后在加载后解析并测量性能。如果文件太大,那么考虑一个带有非常大缓冲区的BufferedInputStream,这可以提高你的性能。
我非常怀疑Simple XML需要花费2分钟来加载4000行,我意识到手机比工作站慢很多,但是我可以在600ms内加载200,000行XML工作站。
答案 7 :(得分:-1)
不要将其作为同步过程,而是使其异步。您可以使用一个启动IntentService的按钮来为您处理数据,并在结束时更新结果并显示通知。这样你就不会停止UI线程了。