Java 使用SimpleXML反序列化的Android速度问题
提出了一个悬赏,因为唯一的答案并没有为Android提供一个好的实现。是否有与Android兼容的更快的实现?还是SimpleXML是我能得到的最好的性能 我是Java和Android开发的新手,因此不知道将xml字符串反序列化为对象的正确过程。我发现了一种适用于以下情况的方法:Java 使用SimpleXML反序列化的Android速度问题,java,android,performance,deserialization,simple-framework,Java,Android,Performance,Deserialization,Simple Framework,提出了一个悬赏,因为唯一的答案并没有为Android提供一个好的实现。是否有与Android兼容的更快的实现?还是SimpleXML是我能得到的最好的性能 我是Java和Android开发的新手,因此不知道将xml字符串反序列化为对象的正确过程。我发现了一种适用于以下情况的方法: public static Object deserializeXMLToObject(String xmlFile,Object objClass) throws Exception { try
public static Object deserializeXMLToObject(String xmlFile,Object objClass) throws Exception
{
try
{
InputStream stream = new ByteArrayInputStream(xmlFile.getBytes("UTF-8"));
Serializer serializer = new Persister();
objClass = serializer.read(objClass, stream);
return objClass;
}
catch (Exception e)
{
return e;
}
}
其中,xmlFile
是(命名错误的)xml字符串,objClass
是我要反序列化到的类的空类。这通常是其他对象的列表
示例类:
@Root(name="DepartmentList")
public class DepartmentList {
@ElementList(entry="Department", inline=true)
public List<Department> DepartmentList =new ArrayList<Department>();
public boolean FinishedPopulating = false;
}
XML示例:
<DepartmentList>
<Department>
<DeptID>525</DeptID>
<DeptDescription>Dept 1</DeptDescription>
</Department>
<Department>
<DeptID>382</DeptID>
<DeptDescription>Dept 2</DeptDescription>
</Department>
</DepartmentList>
525
第一部门
382
第二部门
这在整个应用程序中运行良好,但我已经到了需要反序列化列表中>300个对象的地步。这只需要大约5秒,或者在调试时需要将近一分钟,但是当调试不理想时,用户不满意这种性能和浪费的时间。有没有办法加快速度?或者我还有别的办法吗?最好仅通过更改
反序列化XmlToObject
方法。您可以通过直接序列化为XML并直接从XML反序列化来消除中间(反)序列化步骤,例如使用或
您还可以通过多线程来加快速度。我将假设您想要反序列化的所有XML字符串都位于;或者,您可以同步对正在使用的任何非线程安全集合的访问。使用类似于的方法来最小化线程创建开销
public class DeserializeXML implements Runnable {
private final String xml;
private final ConcurrentLinkedQueue<Object> deserializedObjects;
public DeserializeXML(String xml, ConcurrentLinkedQueue deserializedObjects) {
this.xml = xml;
this.deserializedObjects = deserializedObjects;
}
public void run() {
deserializedObjects.offer(deserializeXMLToObject(xml, Object.class));
}
}
// ***
ConcurrentLinkedQueue<String> serializedObjects;
ConcurrentLinkedQueue<Object> deserializedObjects;
ThreadPoolExecutor executor = new ThreadPoolExecutor;
while(!serializedObjects.isEmpty()) {
executor.execute(new DeserializeXML(serializedObjects.poll(), deserializedObjects));
}
public类反序列化xml实现可运行{
私有最终字符串xml;
私有最终ConcurrentLinkedQueue反序列化对象;
公共反序列化xml(字符串xml、ConcurrentLinkedQueue反序列化对象){
this.xml=xml;
this.deserializedObjects=反序列化对象;
}
公开募捐{
offer(deserializeXMLToObject(xml,Object.class));
}
}
// ***
ConcurrentLinkedQueue序列化对象;
ConcurrentLinkedQueue反序列化对象;
ThreadPoolExecutor executor=新的ThreadPoolExecutor;
而(!serializedObjects.isEmpty()){
execute(新的反序列化XML(serializedObjects.poll(),反序列化dObjects));
}
我相信有人会指出一个更好的库,但据我所知,它们在Android上的速度都很慢
因此,下面是我的快速破解(是的,我知道它不是很容易维护,而且对于没有完全按照指定格式形成的XML来说很脆弱)和一些结果:
private void doTest()
{
Thread t = new Thread()
{
public void run()
{
runOne(2000);
runOne(300);
runOne(20000);
}
private void runOne(int num)
{
String start = "<DepartmentList>";
String mid1 = "<Department>\n" +
"<DeptID>";
String mid2 = "</DeptID>\n" +
"<DeptDescription>Dept ";
String mid3 = "</DeptDescription></Department>";
String fin = "</DepartmentList>";
StringBuffer sb = new StringBuffer();
sb.append(start);
for (int i=0; i< num; i++)
{
sb.append(mid1);
sb.append(""+i);
sb.append(mid2);
sb.append(""+i);
sb.append(mid3);
}
sb.append(fin);
Pattern p = Pattern.compile(
"<Department\\s*>\\s*<DeptID\\s*>([^<]*)</DeptID>\\s*<DeptDescription\\s*>([^<]*)</DeptDescription>\\s*</Department>");
long startN = System.currentTimeMillis();
DepartmentList d = new DepartmentList();
List<Department> departments = d.DepartmentList;
Matcher m = p.matcher(sb);
while (m.find())
{
Department department = new Department();
department.DeptID(m.group(1));
department.DeptDescription(m.group(2));
departments.add(department);
}
long endN = System.currentTimeMillis();
Log.d("Departments", "parsed: " + departments.size() + " in " + (endN-startN) + " millis");
Log.d("Departments", "lastone: " + departments.get(departments.size() -1)._DeptID + " desc: " + departments.get(departments.size() -1)._DeptDescription);
}
};
t.start();
}
public class DepartmentList {
public List<Department> DepartmentList =new ArrayList<Department>();
public boolean FinishedPopulating = false;
}
public class Department {
private String _DeptID ="";
public String DeptID()
{
return _DeptID;
}
public void DeptID(String Value)
{
_DeptID = Value;
}
private String _DeptDescription ="";
public String DeptDescription()
{
return _DeptDescription;
}
public void DeptDescription(String Value)
{
_DeptDescription = Value;
}
}
Platform num=300 num=2000 num=20000
=================================================
Nexus 7 5 38 355
Galaxy Y 29 430 1173
HTC Desire HD 19 189 539
Galaxy Nexus 14 75 379
所有时间均以毫秒为单位 使用服务器代理并将XML转换为JSON对于我的研究,这是优化的最佳方式: Simple将动态构建您的对象图,这意味着它将需要加载尚未加载的类,并使用反射基于其注释为每个类构建架构。因此,到目前为止,首次使用总是最昂贵的。重复使用同一个persister实例会快很多倍。因此,尽量避免使用多个persister实例,如果可能,只使用一个。” 因此,重构代码以使用相同的持久化程序应该可以提高性能 在这种情况下,重构提高了性能,正如作者所说(从15秒到3-5秒)
希望对您有所帮助。几次以前,SOAP Web服务也出现了类似的问题。 最后,我更改了XML的格式,转换了属性中的节点 例如:
<node>
<attr1>value1</attr1>
<attr2>value2</attr2>
<attr3>value3</attr3>
<attr4>value4</attr4>
</node>
价值1
价值2
价值3
价值4
在
<node attr1='value1'attr2='value2' attr3='value3' attr4='value4' />
从理论上讲,这可能不是最好的解决方案,但性能改进确实很好。如果XML稍微复杂一点(不同级别的可重复节点或多级列表),则为Ofc事情可能有点复杂。反序列化是在特殊的基础上进行的。当一个事件发生时,它将关闭并反序列化一个字符串,当另一个事件发生时,它将反序列化另一个字符串。它们没有存储在
ConcurrentLinkedQueue
中,我甚至不知道从哪里开始研究它。我研究了JAXB和XStream,也没有研究一个导致了重复包名的问题,另一个只是“不起作用”“我不记得它的确切问题是什么。我会再看一遍这两个软件包,但我希望能有一个JAXB或XStream的教程或工作示例的链接,因为文档似乎很少。好的,在研究了更多之后,这两个软件包似乎都不能与Android一起工作。我要提出一个悬赏。它是这么简单——一种类型有一个列表和两个字段,或者实际上更复杂?它是一种类型,但大约300-400行中可能有30个字段。我只是出于示例目的对其进行了简化。一种可能的解决方案是在不必等待解析器解析整个内容的情况下报告结果XML的速度很慢。考虑使用另一种格式。任何人都能帮助我完成这个链接:最终开始尝试这个方法。虽然我同意这不是最有效的方法,但我只有一个数据表,我需要用这种方式进行反序列化,它提供了最快的解决方案。从6.25s降低到使用同一个持久化器确实提高了性能,但只是略有提高。从6.25秒到5.75秒。0.5s的差异不会对仍会抱怨的用户产生太大影响。
<node attr1='value1'attr2='value2' attr3='value3' attr4='value4' />