1

在我的 AsyncTask 中,我使用 Jsoup 从网页中提取所有 p 标签,然后将它们添加到 ArrayList 中,然后 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 中的日志语句返回 0,而我的列表是空的?

4

2 回答 2

3

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

所以你可以用它来设置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

于 2012-09-25T21:18:37.790 回答
1

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

于 2012-09-25T20:29:42.523 回答