2011-12-12 47 views
0

我的应用程序发出HTTP请求来检索XML文件,然后转换到这一个ListView。 的问题是,当一个包含该列表的视图中打开该应用程序冻结了几秒钟,而内容被下载,解析和转换到ListView控件。 (但它的作品)。如何正确设置AsyncTask以从UI线程分离下载?

我试图实施的AsyncTask(见下面的代码)做处理在后台线程,但我的实现造成了应用程序冻结了比以前更长的时间。

这包括三类:MainActivity类别; ListViewer类;和XMLhelper类。 MainActivity只包含一个Button来调用ListViewer。 ListViewer应该是UI线程。 XMLhelper包含用于发出HttpClient请求的函数。

ListViewer.java(简介):

public class ListViewer extends ListActivity { 

    private ArrayList<HashMap<String, String>> xmlList; 
    private String server; 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.list_view); 

     xmlList = new ArrayList<HashMap<String, String>>(); 
     server = "http://www.myserver.com/xml"; 
     getXMLList(); 
    } 

    public void getXMLList() { 
     Document xmlDocument = XMLhelper.getXMLDocument(server); 
     int numResults = XMLfunctions.numResults(xmlDocument); 
     if (numResults <= 0) { 
      Toast.makeText(this, "No results found.", Toast.LENGTH_LONG).show(); 
      finish(); 
     } 

     NodeList nodes = xmlDocument.getElementsByTagName("result"); 
     for (int i=0; i<nodes.getLength(); i++) { 
      HashMap<String, String> map = new HashMap<String, String>(); 
      Element e = (Element)nodes.item(i); 
      map.put(...); //code omitted 
      xmlList.add(map); 
     } 

     ListAdapter adapter = new SimpleAdapter(this, xmlList, 
      R.layout.list_view_row, 
      new String[] {...}, 
      new int[] {...}); 
     setListAdapter(adapter); 
    } 
} 

XMLhelper.java(简介):

public class XMLhelper { 
    public static class DownloadContentTask extends AsyncTask<String, Void, String> { 
     DownloadContentTask(String... URLs) { 
      this.execute(URLs); 
     } 
     @Override 
     protected String doInBackground(String... URLs) { 
      String xml = null; 
      try { 
       DefaultHttpClient httpClient = new DefaultHttpClient(); 
       HttpPost httpPost = new HttpPost(URLs[0]); 
       HttpResponse httpResponse = httpClient.execute(httpPost); 
       HttpEntity httpEntity = httpResponse.getEntity(); 
       xml = EntityUtils.toString(httpEntity); 
      } catch (...) { 
       xml = "..."; //all exceptions are caught 
      } 
      return xml; 
     } 
    } 

    public static Document getXMLDocument(String server) { 
     DownloadContentTask xmlTask = new DownloadContentTask(new String[] { server }); 
     String xml = ""; 
     try { 
      xml = xmlTask.get(); 
     } catch (...) { 
      //print errors 
     } 
     return XMLfromString(xml); 
    } 

    public static Document XMLfromString(String xml) { ... } 
    public final static String getElementValue(Node elem) { ... } 
    public static int numResults(Document doc) { ... } 
    public static String getValue(Element item, String str) { ... } 
} 

我打算让这个当ListViewer从在MainActivity称为ListView控件是无人居住但立即显示UI,然后一旦内容下载并解析,ListView就会更新。

我在做什么错?

回答

1

很简单,看看在get()方法的文档:

如有必要,等待计算完成,然后获取其结果。

通过调用getXMLDocumentget()您阻止当前线程(UI线程)直到异步任务已经完成。

异步任务应该自己做更新,在UI线程中调用它们,而不是从UI线程返回信息给调用者。

你应该始终阅读文档;)

+0

哦好吧感谢的返回值。我试图在助手类中调用它,以便所有xml文档请求(在我的应用程序中有很多)正在经历这个AsyncTask操作。你知道有一种方法可以做到这一点吗?即onPostExecute以某种方式发送回xml字符串? – Ozzy

+0

正如@bvanvelsen刚刚建议的那样,在'onPostExecute'方法中运行它。使你的AsyncTask'的'子场,将让你在'doInBackground'方法下载的一切,然后在'onPostExecute'显示英寸 – Jong

+0

因此,解决方案是在ListViewer中创建DownloadContentTask的子类?另外我需要重写onPostExecute方法并将结果发布到AsyncTask中的专用字段? – Ozzy

1

您可以覆盖的AsyncTask的onPostExecute方法,这个方法在UI线程上运行,一旦doInBackground()方法结束时调用。你从onPostExecute()方法得到的参数是doInBackground()方法