Listview not updating after database update and adapter.notifyDataSetChanged();

女生的网名这么多〃 提交于 2019-11-29 05:21:55

Using adapter.swapCursor(cursor) is correct so you're almost there in answering your own question.

Your first piece of code doesn't work because when you call fillData() after your database update, you simply call adapter.notifyDataSetChanged() and the dataset hasn't actually changed because the cursor is the same. A cursor is a reference to rows from your database and updating the underlying database doesn't refresh the cursor. Your second piece of code does refresh the cursor and swaps the new one in to the adapter (which also triggers an update to the view it is bound to).

The more common way to code this is:

Add this interface to your activity:

public class MyActivity extends Activity implementsLoaderManager.LoaderCallbacks<Cursor>

In onCreate, set up the adapter (note that the cursor is null at this point):

String[] from = new String[] { TodoTable.COLUMN_SUMMARY, TodoTable.COLUMN_ID};
int[] to = new int[] { R.id.label };
adapter = new SimpleCursorAdapter(this, R.layout.todo_row, null, from, to, 0);  //Note that the cursor is null
lw.setAdapter(adapter);

Initiate the loader:

getLoaderManager().initLoader(0, null, this);

This calls onCreateLoader in a background thread (so if your query is long running it won't block the UI thread). When it finishes, onLoadFinished is called on the UI thread where you can swap in the new cursor.

After you do a delete or update, restart the loader:

getLoaderManager().restartLoader(0, null, this);

This calls onLoaderReset which removes the existing cursor from the adapter and then calls onCreateLoader again to swap in a new one.

Finally add these methods:

public Loader<Cursor> onCreateLoader(int id, Bundle args)
{
    String[] from = new String[] { TodoTable.COLUMN_SUMMARY, TodoTable.COLUMN_ID};
    String where = TodoTable.COLUMN_DELETED + " = ?";

    Loader<Cursor> loader = new CursorLoader(this, TodoContentProvider.CONTENT_URI, from, where, new String[] {"0"}, null);     
    return loader;
}

public void onLoadFinished(Loader<Cursor> loader, Cursor cursor)
{
    adapter.swapCursor(cursor);
}

public void onLoaderReset(Loader<Cursor> loader)
{
    adapter.swapCursor(null);
}

Here below is my working solution. Briefly, I am updating the underlying database in a service and when the service finishes its job it calls the activity with a localbroadcastmanager. I use List and BaseAdapter.

In the service, I call:

    Intent intent = new Intent("notifyactivity");
    LocalBroadcastManager.getInstance(this).sendBroadcast(intent);

In the activity:

    @Override
        public void onResume() {
        super.onResume();
       LocalBroadcastManager.getInstance(this).registerReceiver(mMessageReceiver,new IntentFilter("notifyactivity"));
}

private BroadcastReceiver mMessageReceiver = new BroadcastReceiver() {
  @Override
  public void onReceive(Context context, Intent intent) {         
      applicationcontacts.clear(); //clear the list first
      applicationcontacts.addAll(db.getAllContacts()); //reload the list
      listview=(ListView) findViewById(R.id.listview1);
      listview.setAdapter(listadaptor);
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                listadaptor.notifyDataSetChanged();
            }
        });
  }
};

@Override
protected void onPause() {
  LocalBroadcastManager.getInstance(this).unregisterReceiver(mMessageReceiver);
  super.onPause();
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!