ArrayList没有在AsyncTask中填充

时间:2012-09-25 19:44:44

标签: android android-asynctask

在我的AsyncTask中,我使用Jsoup从网页中提取所有p标记,然后将它们添加到然后由ArrayAdapter用于填充屏幕的ArrayList中。帖子,但由于某种原因,当我在方法之后检查它时,ArrayList是空的。

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    newsItems = new ArrayList<String>();

    fillNewsItems();
    setListAdapter(new ArrayAdapter<String>(this,
            android.R.layout.simple_list_item_1,
            newsItems));
    Log.d("news", Integer.toString(newsItems.size()));
}

private class GetNewsItemsTask extends AsyncTask<String, Void, String> {

    protected String doInBackground(String... urls) {
        try {
            Document doc = Jsoup.connect(URL).get();
            for (Element e : doc.getElementsByTag("p")) {
                newsItems.add(e.text());
            }
        } catch (Exception e) {     
            Toast.makeText(getApplicationContext(), "Couldn't fetch articles, try again later.",
                    Toast.LENGTH_SHORT).show();
        }           
        return null;
    }
}

private void fillNewsItems() {
    GetNewsItemsTask getNews = new GetNewsItemsTask();
    getNews.execute(URL);
}
}

有谁知道为什么onCreate中的log语句返回0,而我的列表是空的?

2 个答案:

答案 0 :(得分:3)

AsyncTask比你现在使用的可能性更大。基本上AsyncTask是一个线程(默认情况下不能更改UI元素)但它提供了一个特殊功能:它与方法onPostExecute()中的UI线程同步。

因此,您可以使用此功能在ArrayAdapter内设置AsyncTask。您可以随意使用onPreExecute()来显示信息对话框。

这段代码应该诀窍:

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    fillNewsItems();

    Log.d("news", Integer.toString(newsItems.size()));
}

private class GetNewsItemsTask extends AsyncTask<Void, Void, ArrayList<String>> {

    protected ArrayList<String> doInBackground(Void... urls) {
        try {
            ArrayList<String> items = new ArrayList<String>();
            Document doc = Jsoup.connect(URL).get();
            for (Element e : doc.getElementsByTag("p")) {
                items.add(e.text());
            }
        } catch (Exception e) {
            Toast.makeText(getApplicationContext(), "Couldn't fetch articles, try again later.",
                    Toast.LENGTH_SHORT).show();
        }
        return items;
    }

    @Override
    protected void onPostExecute(ArrayList<String> items) {
        newsItems = items; // I assume that newsItems is used elsewhere.
                           // If that's not the case -> remove it
        setListAdapter(new ArrayAdapter<String>(this,
                android.R.layout.simple_list_item_1,
                items));
    }
}

private void fillNewsItems() {
    GetNewsItemsTask getNews = new GetNewsItemsTask();
    getNews.execute();
}

这是关于Android中异步编程的一个很好的教程:Android Threads, Handlers and AsyncTask

答案 1 :(得分:1)

很可能是因为AsyncTask还没有完成执行。 AsyncTask就是这样,异步。它同时在后台运行。 看起来您希望代码在fillNewsItems()之前阻塞,直到AsyncTask为止 已经完成,实际上它几乎立即返回,就在启动AsyncTask之后。因此,当您尝试获取列表的大小时,它仍为零,AsyncTask尚未完成。