HpTerm
HpTerm

Reputation: 8281

Populating listview in separate thread

In an activity I load rows of a listview which takes much time, therefore I put this task in a separate thread to allow displaying a progressDialog.

I do the following

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();
        }
    };
};

I have sometimes a bug which raises an IllegalStateException. First of all I was surprised, because programming thread like that is what I usually do in standard Java programs.

The bug appears only "sometimes" and it does not appear when doing step by step debugging.

This lead me to search around the web and I found some questions in SO related to this and I must admit that things are not clear to my mind.

As I call the notifyDataSetChanged() only when the thread finished why does it sometimes raises an exception.

Can someone confirm me that this way of doing is wrong, and that I MUST use async task and perhaps explain me why ???

I need to have a progressDialog displayed, can someone give me a simple example of AsyncTask populating a listview AND displaying a progressDialog of the populating progress.

Thanks

UPDATE

jtanveer gave me the answer to the asynctask question. Now the others pointed out that the dismiss is not in the handler, which I correct.

According to the article given by jtanveer on "Painless Threading" they say that

Android offers several ways to access the UI thread from other threads which one of them is HANDLER.

Does someone know why putting the dismissed in the handler did not solve my problem ? for me listItem.add has nothing to do with UI ? Am I wrong on that point ?

For me, in my code the only UI is adapter and progressdialog ? Any commentary or explanation is welcome.

FINAL ANSWER

stjom gave a working answer for my specific code. Running the runOnUiThread in the handler. It's working but I am surprised because I thought the handler was run in the Ui Thread ...

Thanx to all for all your answers.

Upvotes: 3

Views: 8461

Answers (3)

PinoyCoder
PinoyCoder

Reputation: 1112

whenever you call adapter.notifyDataSetChanged(); it identifies any changes to your listItems object. if any change is found, it will update the UI accordingly which I think causes your problem. you can call

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

inside your handler.

Upvotes: 2

Splash
Splash

Reputation: 1340

You don't need to use AsyncTask, its just a convenience.

As far as why your current implementation doesn't work sometimes - You should dismiss your progress dialog from the UI thread, so that needs to go in your handler, not your background thread.

Upvotes: 2

jamael
jamael

Reputation: 398

define an inner class like below:

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();
        }
    }
}

if you need, you can refer to this article.

Upvotes: 3

Related Questions