在单独的线程中填充listview

时间:2012-05-04 20:08:51

标签: android multithreading listview android-asynctask

在一个活动中,我加载了listview的行,这需要花费很多时间,因此我将此任务放在一个单独的线程中以允许显示progressDialog。

我做以下

private void doMyStuff() {
    listItems.clear();
    progressDialog.show();

    new Thread(new Runnable() {
        @Override
        public void run() {                
            for () {
                listItems.add(something to add);
            }
        handler.sendEmptyMessage(0);
        progressDialog.dismiss();
        }
    }).start();
}

private Handler handler = new Handler() {
    public void handleMessage(android.os.Message msg) {
        if (msg.what == 0) {
            adapter.notifyDataSetChanged();
        }
    };
};

我有时会出现一个引发IllegalStateException的错误。首先,我感到很惊讶,因为这样的编程线程是我在标准Java程序中通常所做的。

该错误仅在“有时”出现,并且在逐步调试时不会出现。

这引导我在网上搜索,我在SO中发现了一些与此相关的问题,我必须承认事情并不清楚。

因为我只在线程结束时才调用notifyDataSetChanged(),为什么它有时会引发异常。

有人可以向我证实这种做法是错误的,我必须使用异步任务,也许可以解释一下为什么???

我需要显示progressDialog,有人可以给我一个简单的AsyncTask示例,用于填充列表视图并显示填充进度的progressDialog。

由于

更新

jtanveer给了我asynctask问题的答案。现在其他人指出解雇不在处理程序中,我纠正了。

根据jtanveer关于“无痛线程”的文章,他们说

Android提供了几种从其他线程访问UI线程的方法,其中一个是HANDLER。

有人知道为什么把被解雇者放入处理程序并没有解决我的问题吗?对我来说listItem.add与UI无关?我错了吗?

对我来说,在我的代码中,唯一的UI是适配器和progressdialog?欢迎任何评论或解释。

最终答案

stjom为我的具体代码提供了有效的答案。在处理程序中运行runOnUiThread。它工作但我很惊讶,因为我认为处理程序是在Ui线程中运行的......

感谢所有人的所有答案。

3 个答案:

答案 0 :(得分:3)

定义一个内部类,如下所示:

private class LoadListTask extends AsyncTask<String, Void, Integer> {
    protected void onPreExecute() {
        progressDialog.show();
    }

    protected Integer doInBackground(String... params) {
        for () {
            listItems.add(something to add);
        }
        return 0;
    }

    protected void onPostExecute(Integer result) {
        progressDialog.dismiss();
        if (result == 0) {
           adapter.notifyDataSetChanged();
        }
    }
}

如果您需要,可以参考此article

答案 1 :(得分:2)

您不需要使用AsyncTask,只是方便。

至于为什么你当前的实现有时不起作用 - 你应该从UI线程中删除你的进度对话框,这样就需要进入你的处理程序,而不是你的后台线程。

答案 2 :(得分:2)

每当您致电adapter.notifyDataSetChanged();时,它都会识别您listItems个对象的所有更改。如果发现任何更改,它将相应地更新UI,我认为这会导致您的问题。你可以打电话

runOnUiThread(new Runnable() {
    public void run() {
        adapter.notifyDataSetChanged();
    }  
});

在你的处理程序中。