4

提出赏金作为唯一的答案并没有为 Android 提供良好的实现。是否有更快的实现与 Android 兼容?还是 SimpleXML 是我将获得的最佳性能?

我对 Java 和 Android 开发相当陌生,所以不知道将 xml 字符串反序列化为对象的正确过程。我找到了一种适用于的方法:

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;
}

部门类:

public class Department {

    @Element(name="DeptID")
    private String _DeptID ="";
    public String DeptID()
    {
        return _DeptID;
    }
    public void DeptID(String Value)
    {
        _DeptID = Value;
    }

    @Element(name="DeptDescription")
    private String _DeptDescription ="";
    public String DeptDescription()
    {
        return _DeptDescription;
    }
    public void DeptDescription(String Value)
    {
        _DeptDescription = Value;
    }
}

示例 XML:

<DepartmentList>
  <Department>
    <DeptID>525</DeptID>
    <DeptDescription>Dept 1</DeptDescription>
  </Department>
  <Department>
    <DeptID>382</DeptID>
    <DeptDescription>Dept 2</DeptDescription>
  </Department>
</DepartmentList>

这在整个应用程序中运行良好,但我已经到了需要反序列化列表中 >300 个对象的地步。这仅需要大约 5 秒,或者在调试时接近一分钟,但用户对这种性能并不满意,并且在不需要调试时浪费了时间。有什么办法可以加快这个速度吗?还是我应该这样做的另一种方式?最好只通过改变deserializeXMLToObject方法。

4

5 回答 5

6

我相信有人会指出那里有一个更好的库,但是根据一个详细的答案,它们在 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;
    }
}

我将它粘贴到一个 Android 项目中,并从 onCreate() 方法中调用它。结果如下:

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

所有时间都以毫秒为单位。

于 2013-05-02T11:36:17.040 回答
3

对于我的研究,这是优化的最佳方法:

“Simple 将动态构建您的对象图,这意味着它将需要加载尚未加载的类,并使用反射基于其注释为每个类构建一个模式。因此,第一次使用将永远是迄今为止最昂贵的. 重复使用同一个持久化实例会快很多倍。所以尽量避免使用多个持久化实例,尽可能只使用一个。

因此,重构您的代码以使用相同的 Persister 应该可以提高您的性能。

我从这个问题中得到的这个和其他提示。在那种情况下,这种重构提高了性能,正如作者所说(从 15s 到 3-5s)。

希望能帮助到你

于 2013-05-07T23:25:49.253 回答
2

您可以通过直接序列化为 XML 并直接从 XML 反序列化(例如使用JAXBXStream )来消除中间(反)序列化步骤。

您还可以通过多线程加快速度。我假设您要反序列化的所有 XML 字符串都在ConcurrentLinkedQueue中;或者,您可以同步访问您正在使用的任何非线程安全集合。使用类似ThreadPoolExecutor的东西来最小化线程创建开销。

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));
}
于 2013-04-10T13:51:00.420 回答
0

很久以前就有一个与 SOAP Web 服务类似的问题。最后我改变了 XML 的格式,转换了属性中的节点。

例子:

<node>
  <attr1>value1</attr1>
  <attr2>value2</attr2>
  <attr3>value3</attr3>
  <attr4>value4</attr4>
</node>

被转化为

<node attr1='value1'attr2='value2' attr3='value3' attr4='value4' />

从理论上讲,也许不是最好的解决方案,但性能改进确实很好。Ofc 如果您的 XML 有点复杂(不同级别或多级列表的可重复节点),事情可能会有点复杂。

于 2013-05-08T07:51:57.827 回答
-1

使用服务器代理并将您的 XML 转换为 JSON

于 2013-05-06T21:33:54.537 回答