I have had this "issue" for sometime on my app and it always bothered me that I didn't understand it's behavior, but never cared about asking why, until now.
I have a ListView
(implemented through a ListActivity
) with a custom layout for each list item. With that I have a custom CursorAdapter
to properly fill all the list item elements (overriding newView
and bindView
, the ViewHolder pattern is already guaranteed when doing it like this, refer to: https://codereview.stackexchange.com/q/1057 if needed).
This is the main Activity and there are 2 actions that can update the content of the ListView
, create a new item or edit a current one. For both, the same activity is used (which adapts itself to the type of action), something like this:
startActivityForResult(intent, ACTIVITY_NOTE_EDITOR_CREATE);
startActivityForResult(intent, ACTIVITY_NOTE_EDITOR_EDIT);
What actually distinguishes the action type is the intent contents, the requestCode
is ignored in the sub activity.
Now, the documentation has this to say about the method above:
When this activity exits, your onActivityResult() method will be called with the given requestCode.
But I'm not using onActivityResult
. Actually, I'm not doing anything when the sub activity exists (either in create or edit mode). And the behavior I've noticed so far is this:
ListView
is automatically updated with the new item. However, sometimes, rarely though, the ListView
is not populated with the new item. I need to destroy the main activity (exiting the app for instance) and recreate it and then the new item will be there.ListView
was always automatically updated with the new content changes.My question is, what's happening behind the scenes that makes my ListView
to automatically update it's contents when I never call cursor.requery()
nor manually notify of any changes to the content? And why the hell doesn't it work all the time?
Should I maybe force a cursor.requery()
myself on onActivityResult
?
public class MainActivity extends ListActivity {
private static final int ACTIVITY_NOTE_EDITOR_CREATE = 0;
private NotificationHelper mNotificationHelper;
private AgendaNotesAdapter mAgendaAdapter;
private Cursor mAllNotesCursor;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mNotificationHelper = Program.getNotificationHelper();
mAgendaAdapter = new AgendaNotesAdapter(this);
mAgendaAdapter.open();
initializeNotesListActivity();
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
Intent intent;
switch(item.getItemId()) {
case R.id.actionbar_item_new_note:
intent = NoteEditorMainActivity.createIntent(this);
startActivityForResult(intent, ACTIVITY_NOTE_EDITOR_CREATE);
return true;
}
return false;
}
private void initializeNotesListActivity() {
mAllNotesCursor = mAgendaAdapter.fetchAllNotes();
startManagingCursor(mAllNotesCursor);
NotesListAdapter notesAdapter = new NotesListAdapter(this, mAllNotesCursor,
mNotificationHelper, mAgendaAdapter);
setListAdapter(notesAdapter);
}
}
P.S: I know about CursorLoader and it's something in the roadmap, but I don't have time to deal with such code rewrites for the time being. Just thought I'd let you know. For now, I just need to know what is happening with my current code.
Your call to startManagingCursor()
means that when the activity is stopped, the Cursor
is deactivated, and when the activity is restarted, the Cursor
is requeried.
Should I maybe force a cursor.requery() myself on onActivityResult?
This should automatically occur for your managed Cursor
.