我已经为此苦苦挣扎了很长时间,经过长时间的研究,我认为是时候在这里发布这个问题了。所以这就是问题所在。我正在开发一个 Android 应用程序,它基本上是一个非常大的系统的数据库端口,用于快速咨询。所以我有一个必须通过 web 服务调用更新的 SQLite 数据库。
为此,我使用 SOAP 调用一些 Web 服务,并使用 SAXParser 解析响应。但问题就在这里。每个页面或更新都需要很长时间,因为解析 500 项 XML 并更新数据库需要大约 20 秒。这是一个问题,因为在最坏的情况下,应用程序将进行 2000 次 Web 服务调用。
我考虑过两种方法来进行 XML 解析。第一个(我们称之为 Approach1)是解析整个回调,将信息保存在对象数组中,然后通过事务更新 DB。第二个(Approach2)是在我解析 XML 时更新数据库。所以,每次我完成一个项目的解析,我都会做一个 BD 插入。
这是我使用的代码
方法1
public class ContactsParser extends DefaultHandler
{
private String foundData = "";
private ContactObj[] contactObj;
private int objectLength = 3000;
private int totalContacts = 0;
private long initiationTime;
private Context dbContext;
public void setObjectLength(int oLength){
objectLength = oLength;
}
public void setContext(Context ctx) {
dbContext = ctx;
}
public synchronized void parse(InputStream is)
throws ParserConfigurationException, SAXException, IOException
{
SAXParserFactory spf = SAXParserFactory.newInstance();
SAXParser sp = spf.newSAXParser();
XMLReader xr = sp.getXMLReader();
xr.setContentHandler(this);
xr.parse(new InputSource(is));
}
@Override
public void characters(char ch[], int start, int length)
{
foundData += new String(ch, start, length);
}
@Override
public void startDocument() throws SAXException
{
//Initialize the array of objects with the length of the Webservice page.
totalContacts = 0;
initiationTime = System.currentTimeMillis();
contactObj = new ContactObj[objectLength];
}
@Override
public void startElement(String namespaceURI, String localName,
String qName, Attributes atts) throws SAXException
{
foundData = "";
try{
if (totalContacts == 0) {
companiesObj[totalContacts] = new CompaniesObj();
}
}
catch (Exception e){
// Catch error
}
}
@Override
public void endElement(String namespaceURI, String elementName, String qName)
throws SAXException
{
if(qName.equals("contactItem")) {
if (totalContacts < objectLength){
contactObj[totalContacts] = new ContactObj();
}
/**
* <contactItem>
* <contactAtt1>value</contactAtt1>
* <contactAtt2>value</contactAtt2>
* </contactItem>
*/
try {
if(qName.equals("contactAtt1"))
{
contactObj[totalContacts].setContactAtt1(foundData);
}
else if(qName.equals("contactAtt2"))
{
contactObj[totalContacts].setContactAtt2(foundData);
}
catch(Exception e)
{
// catch error
}
}
@Override
public void endDocument() throws SAXException
{
try {
//DBHelper is a class that performs all DB related processes.
//getInstance sees if the instance of the object DBHelper.self exists. If not, it creates it.
DBHelper.getInstance(dbContext).db.beginTransaction();
for (int i = 0; i < totalContacts; i++){
DBHelper.self.sqLiteConctacts.insertRow(contactObj[i]);
}
DBHelper.self.db.setTransactionSuccessful();
} catch (Exception e){
// catch this exception
} finally {
DBHelper.self.db.endTransaction();
DBHelper.self.closeDB();
}
Logger.logMessage("Requried time to complete ContactParseing: "+(System.currentTimeMillis()-initiationTime));
Logger.logMessage("Parsing ended of ContactParser:" + totalContacts);
}
}
这种方法具有使用事务进行更新的巨大优势,但代价是必须在进行更新之前解析整个文档。
方法2
public class ContactsParseAndInsert extends DefaultHandler
{
private String foundData = "";
private int totalContacts = 0;
private long initiationTime;
private Context dbContext;
// Contact attributes
private String contactAtt1 = "";
private String contactAtt2 = "";
public void setContext(Context ctx) {
dbContext = ctx;
}
public synchronized void parse(InputStream is)
throws ParserConfigurationException, SAXException, IOException
{
SAXParserFactory spf = SAXParserFactory.newInstance();
SAXParser sp = spf.newSAXParser();
XMLReader xr = sp.getXMLReader();
xr.setContentHandler(this);
xr.parse(new InputSource(is));
}
@Override
public void characters(char ch[], int start, int length)
{
foundData += new String(ch, start, length);
}
@Override
public void startDocument() throws SAXException
{
//Initialize the array of objects with the length of the Webservice page.
totalContacts = 0;
initializationTime = System.currentTimeMillis();
DBHelper.getInstance(dbContext);
Logger.logMessage("Parsing started of ContactParser With instant insert.");
}
@Override
public void startElement(String namespaceURI, String localName,
String qName, Attributes atts) throws SAXException
{
foundData = "";
}
@Override
public void endElement(String namespaceURI, String elementName, String qName)
throws SAXException
{
if(qName.equals("ContactItem")) {
DBHelper.self.sqLiteConctacts.insertRow(contactAtt1, contactAtt2);
}
/**
* <companiesObj>
* <contactAtt1>value</contactAtt1>
* <contactAtt2>value</contactAtt2>
* </companiesObj>
*/
try {
if(qName.equals("contactAtt1"))
{
contactAtt1 = foundData;
}
else if(qName.equals("contactAtt2"))
{
contactAtt2 = foundData;
}
catch(Exception e)
{
// catch error
}
}
@Override
public void endDocument() throws SAXException
{
DBHelper.self.closeDB();
Logger.logMessage("Requried time to complete ContactParseing: "+(System.currentTimeMillis()-initiationTime));
Logger.logMessage("Parsing ended of ContactParser:" + totalContacts);
}
}
第二种方法的优点是我可以让 XML 随心所欲,而且不会有任何内存问题。但是这样就不可能有数据库事务。
另一件重要的事情是,所有这一切都发生在运行它自己的线程并通过 Messenger 与我的活动通信的服务中。
他们都正确地完成了工作,但我宁愿使用第二种方法。谁能告诉我如何加快速度?有人知道更好的方法吗?以下是我在日志中得到的结果。(所有那些 dalvikvm 的停顿让我有点担心)
09-13 12:31:42.653: I/MyFaultyApp(6477): Parsing started of ContactParser With instant insert.
09-13 12:31:42.653: I/MyFaultyApp(6477): --------------------------------------------------------
09-13 12:31:43.563: D/dalvikvm(6477): GC_CONCURRENT freed 418K, 29% free 2458K/3459K, paused 11ms+1ms, total 32ms
09-13 12:31:45.213: D/dalvikvm(6477): GC_CONCURRENT freed 427K, 30% free 2432K/3459K, paused 11ms+14ms, total 35ms
09-13 12:31:46.493: D/dalvikvm(6477): GC_CONCURRENT freed 389K, 30% free 2431K/3459K, paused 14ms+12ms, total 36ms
09-13 12:31:47.663: D/dalvikvm(6477): GC_CONCURRENT freed 411K, 30% free 2433K/3459K, paused 1ms+2ms, total 13ms
09-13 12:31:49.213: D/dalvikvm(6477): GC_CONCURRENT freed 420K, 30% free 2432K/3459K, paused 1ms+12ms, total 25ms
09-13 12:31:50.273: D/dalvikvm(6477): GC_CONCURRENT freed 415K, 30% free 2433K/3459K, paused 1ms+1ms, total 14ms
09-13 12:31:51.203: D/dalvikvm(6477): GC_CONCURRENT freed 410K, 30% free 2432K/3459K, paused 1ms+1ms, total 16ms
09-13 12:31:52.183: D/dalvikvm(6477): GC_CONCURRENT freed 415K, 30% free 2432K/3459K, paused 1ms+2ms, total 19ms
09-13 12:31:53.123: D/dalvikvm(6477): GC_CONCURRENT freed 399K, 30% free 2430K/3459K, paused 11ms+12ms, total 34ms
09-13 12:31:53.653: D/dalvikvm(6477): GC_CONCURRENT freed 392K, 30% free 2430K/3459K, paused 11ms+1ms, total 22ms
09-13 12:31:54.423: D/dalvikvm(6477): GC_CONCURRENT freed 407K, 30% free 2433K/3459K, paused 11ms+1ms, total 23ms
09-13 12:31:55.103: D/dalvikvm(6477): GC_CONCURRENT freed 408K, 30% free 2435K/3459K, paused 12ms+12ms, total 36ms
09-13 12:31:55.623: D/dalvikvm(6477): GC_CONCURRENT freed 413K, 30% free 2435K/3459K, paused 11ms+14ms, total 36ms
09-13 12:31:56.793: D/dalvikvm(6477): GC_CONCURRENT freed 410K, 30% free 2435K/3459K, paused 11ms+15ms, total 36ms
09-13 12:31:57.493: D/dalvikvm(6477): GC_CONCURRENT freed 416K, 30% free 2431K/3459K, paused 1ms+2ms, total 14ms
09-13 12:31:58.563: I/MyFaultyApp(6477): Requried time to complete ContactParseing: 15910
09-13 12:31:58.563: I/MyFaultyApp(6477): --------------------------------------------------------
09-13 12:31:58.563: I/MyFaultyApp(6477): Parsing ended of ContactParser:500
09-13 12:31:58.563: I/MyFaultyApp(6477): --------------------------------------------------------
09-13 12:31:58.573: D/dalvikvm(6477): GC_CONCURRENT freed 407K, 30% free 2439K/3459K, paused 13ms+3ms, total 28ms
09-13 12:32:00.503: I/MyFaultyApp(6477): Parsing started of ContactParser With instant insert.
09-13 12:32:00.503: I/MyFaultyApp(6477): --------------------------------------------------------
09-13 12:32:00.803: D/dalvikvm(6477): GC_CONCURRENT freed 399K, 29% free 2460K/3459K, paused 12ms+1ms, total 34ms
09-13 12:32:01.233: D/dalvikvm(6477): GC_CONCURRENT freed 440K, 30% free 2431K/3459K, paused 13ms+1ms, total 26ms
09-13 12:32:01.953: D/dalvikvm(6477): GC_CONCURRENT freed 404K, 30% free 2435K/3459K, paused 11ms+2ms, total 24ms
09-13 12:32:03.643: D/dalvikvm(6477): GC_CONCURRENT freed 413K, 30% free 2432K/3459K, paused 1ms+12ms, total 24ms
09-13 12:32:06.313: D/dalvikvm(6477): GC_CONCURRENT freed 386K, 29% free 2472K/3459K, paused 11ms+1ms, total 31ms
09-13 12:32:08.433: D/dalvikvm(6477): GC_CONCURRENT freed 457K, 30% free 2434K/3459K, paused 11ms+1ms, total 30ms
09-13 12:32:09.733: D/dalvikvm(6477): GC_CONCURRENT freed 423K, 30% free 2436K/3459K, paused 13ms+12ms, total 44ms
09-13 12:32:13.873: D/dalvikvm(6477): GC_CONCURRENT freed 405K, 30% free 2431K/3459K, paused 13ms+2ms, total 25ms
09-13 12:32:15.743: D/dalvikvm(6477): GC_CONCURRENT freed 411K, 30% free 2433K/3459K, paused 1ms+1ms, total 14ms
09-13 12:32:18.593: D/dalvikvm(6477): GC_CONCURRENT freed 412K, 30% free 2435K/3459K, paused 1ms+1ms, total 13ms
09-13 12:32:20.752: D/dalvikvm(6477): GC_CONCURRENT freed 386K, 29% free 2467K/3459K, paused 14ms+11ms, total 34ms
09-13 12:32:22.003: D/dalvikvm(6477): GC_CONCURRENT freed 445K, 30% free 2436K/3459K, paused 1ms+1ms, total 14ms
09-13 12:32:23.113: D/dalvikvm(6477): GC_CONCURRENT freed 421K, 30% free 2435K/3459K, paused 11ms+2ms, total 32ms
09-13 12:32:24.033: D/dalvikvm(6477): GC_CONCURRENT freed 385K, 30% free 2442K/3459K, paused 13ms+5ms, total 27ms
09-13 12:32:24.902: D/dalvikvm(6477): GC_CONCURRENT freed 415K, 30% free 2433K/3459K, paused 11ms+1ms, total 28ms
09-13 12:32:25.203: I/MyFaultyApp(6477): Requried time to complete ContactParseing: 24707
09-13 12:32:25.203: I/MyFaultyApp(6477): --------------------------------------------------------
09-13 12:32:25.203: I/MyFaultyApp(6477): Parsing ended of ContactParser:500
09-13 12:32:25.203: I/MyFaultyApp(6477): --------------------------------------------------------
谢谢你,很抱歉这么长的帖子。