Как правильно настроить AsyncTask, чтобы отделить загрузку от потока пользовательского интерфейса? - PullRequest
0 голосов
/ 13 декабря 2011

Мое приложение отправляет HTTP-запрос на получение XML-файла, а затем переводит его в ListView.Проблема заключается в том, что при открытии представления, содержащего этот список, приложение останавливается на несколько секунд, пока содержимое загружается, анализируется и транслируется в ListView.(Но это работает).

Я пытался реализовать AsyncTask (см. Код ниже) для выполнения обработки в фоновом потоке, но моя реализация вызвала зависание приложения на гораздо более длительное время, чем раньше.

Это включает три класса: класс MainActivity;Класс ListViewer;и класс XMLhelper.MainActivity просто содержит кнопку для вызова ListViewer.Предполагается, что ListViewer является потоком пользовательского интерфейса.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 список List не заполнялся, но пользовательский интерфейс показывался немедленно, а затем, как только содержимое загружалось и анализировалось, ListView обновляется.

Что я делаю неправильно?

Ответы [ 2 ]

1 голос
/ 13 декабря 2011

вы можете переопределить метод onPostExecute в AsyncTask, этот метод выполняется в потоке пользовательского интерфейса и вызывается после завершения метода doInBackground ().параметр, который вы получаете из метода onPostExecute (), является возвращаемым значением метода doInBackground ()

1 голос
/ 13 декабря 2011

Довольно просто, взгляните на документацию по методу get():

При необходимости ожидает завершения вычисления, а затем извлекает его результат.

При вызове get() в getXMLDocument вы блокируете текущий поток (поток пользовательского интерфейса) до асинхронная задача выполнена.

Асинхронная задача должна выполнять обновления самостоятельно, вызывать их в потоке пользовательского интерфейса, а не возвращать информацию вызывающей стороне из потока пользовательского интерфейса.

И вы всегда должны читать документацию;)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...