簡體   English   中英

如何正確設置AsyncTask以將下載與UI線程分開?

[英]How can I set-up an AsyncTask properly to separate downloading from the UI thread?

我的應用程序發出HTTP請求來檢索XML文件,然后將其轉換為ListView。 問題是,當打開包含該列表的View時,應用程序凍結幾秒鍾,同時內容被下載並解析並轉換到ListView。 (但它確實有效)。

我試圖在后台線程中實現AsyncTask(參見下面的代碼)來處理,但是我的實現導致應用程序凍結的時間比以前長得多。

這涉及三個類:MainActivity類; ListViewer類; 和XMLhelper類。 MainActivity只包含一個用於調用ListViewer的Button。 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) { ... }
}

我打算這樣做,以便當從MainActivity調用ListViewer時,ListView未填充但是UI立即顯示,然后一旦內容被下載並解析,ListView就會更新。

我究竟做錯了什么?

很簡單,看看get()方法文檔:

如果需要等待計算完成,然后檢索其結果。

通過在getXMLDocument調用get() ,您可以阻止當前線程(UI線程), 直到完成異步任務。

異步任務應該自己進行更新,在UI線程中調用它們,而不是從UI線程將信息返回給調用者。

你應該總是閱讀文檔;)

您可以覆蓋AsyncTask中的onPostExecute方法,此方法在UI線程上運行,並在doInBackground()方法完成后調用。 從onPostExecute()方法獲得的參數是doInBackground()方法的返回值

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM