Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
524 views
in Technique[技术] by (71.8m points)

android - Refresh a SimpleCursorAdapter after performing work on a non-UI thread

I'm trying to call .notifyDataSetChange() on a SimpleCursorAdapter displayed in a ListView from an XML-parsing non-UI thread and can't for the life of me figure out how. I've searched all over and all I've found are articles that talk about refreshing from within the ListView itself, which I'm not doing. I can't figure out a way to pass in the adapter or get it from the parent or whatever I need to do to call a method on it from another thread.

The ListView will update fine the next time I launch the activity, but I want it to refresh as soon as the XML parsing is done so that the user will see the new data immediately.

The answer's probably simple; it's just eluding me. Thanks in advance for any help!

Here's my code:

public class DirectoryListActivity extends DirectoryActivity {

public final Handler mHandler = new Handler();

@Override
public void onCreate(Bundle savedInstanceState) {

    super.onCreate(savedInstanceState);
    setContentView(R.layout.directory_list);

    // Populate the ListView
    SQLiteQueryBuilder queryBuilder = new SQLiteQueryBuilder();
    queryBuilder.setTables(
        directoryPeople.PEOPLE_TABLE
    );

    String asColumnsToReturn[] = { 
            //snip
    };

    mCursor = queryBuilder.query(mDB, asColumnsToReturn, null, null,
            null, null, directoryPeople.DEFAULT_SORT_ORDER);

    startManagingCursor(mCursor);

// HERE'S THE ADAPTER
    SimpleCursorAdapter adapter = new SimpleCursorAdapter(this,
            R.layout.directory_people_item, mCursor,
            new String[]{
                //snip
            new int[]{
                //snip
    ); 

    ListView av = (ListView)findViewById(R.id.listPeople);
    av.setAdapter(adapter);

    //Perform sync in background
    startXMLParseThread();

}

    public void startXMLParseThread() {

    new Thread () {

        boolean success = false;

        public void run() {
            try {
                // XML-Parsing and Table-Updating code

            } catch (Exception e) {
                success = false;
            }

            mHandler.post(new Runnable() {
                public void run() {
                    TextView txtUpdateStatus = (TextView)findViewById(R.id.txtUpdateStatus);
                    if (success) {
                        txtUpdateStatus.setText(R.string.synced);
                    } else {
                        txtUpdateStatus.setText(R.string.sync_failed);
                    }
                    adapter.notifyDataSetChanged(); // ECLIPSE HATES
                }
            });
        }
    }.start();
    }
}
}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

No need to create a new adapter...

.notifyDataSetChanged() should be called only in case the data rows actually changed (inserted or deleted rows), in case you just updated the values on rows a simple call to requery() on your cursor should be enough:

adapter.getCursor().requery();

Edit: by your comment I see that you have in fact a compilation problem...

You must declare the adapter as a class member (before/after mHandler declare it: private SimpleCursorAdapter adapter)

Then when you initialize it, replace

SimpleCursorAdapter adapter = new SimpleCursorAdapter(this,
    R.layout.directory_people_item, mCursor,
    new String[]{
        //snip
        new int[]{
        //snip
); 

with:

adapter = new SimpleCursorAdapter(this,
    R.layout.directory_people_item, mCursor,
    new String[]{
        //snip
        new int[]{
        //snip
); 

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...