I have an SherlockFragmentActivity that is showing a few tabs. Each tab is ListFragment.
Each ListFragment is getting created like so:
ActionBar bar = getSupportActionBar();
bar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
bar.setDisplayOptions(0, ActionBar.DISPLAY_SHOW_TITLE);
bar.setDisplayHomeAsUpEnabled(true);
bar.setDisplayShowTitleEnabled(true);
// users event list
bar.addTab(bar.newTab()
.setTag("contacts_list")
.setText(getString(R.string.list_contacts_header))
.setTabListener(new TabListener<ContactListFragment>(
this, getString(R.string.list_events_header), ContactListFragment.class, null)));
Then, each of the ListFragments are loaded like so:
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
// database cursor containing all venues for this event
venuesCursor = getDatasource().getAllVenues(((EventActivity) getActivity()).getEventId());
// hand the cursor to the system to manage
getActivity().startManagingCursor(venuesCursor);
// bind the columns of the cursor to the list
String[] from = new String[] { VenuesDataSource.KEY_NAME, VenuesDataSource.KEY_DESCRIPTION };
int[] to = new int[] { R.id.list_item_title, R.id.list_item_subtitle };
cursorAdapter = new SimpleCursorAdapter(getActivity(), R.layout.list_item, venuesCursor, from, to);
// retrieve the listview to populate
ListView lv = (ListView) getActivity().findViewById(android.R.id.list);
// set the adapter on the listview
lv.setAdapter(cursorAdapter);
// click event for each row of the list
lv.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> arg0, View view,
int position, long id) {
Cursor cursor = cursorAdapter.getCursor();
cursor.moveToPosition(position);
Toast.makeText(getActivity(), "Tapped row " + position + "!", Toast.LENGTH_SHORT).show();
}
});
// Start out with a progress indicator.
setListShown(false);
// prepare the loader -- either re-connect with an existing one, or start a new one.
// getLoaderManager().initLoader(0, null, this);
// load the data
getActivity().getSupportLoaderManager().initLoader(0, null, this);
}
Like I said, there are multiple tabs on this activity in the form of ListFragments. The issue I'm having is that when clicking on the tabs to select them, I get
E/AndroidRuntime(2519): java.lang.IllegalArgumentException: column 'name' does not exist
Which is wrong, I've used adb to view the database, the columns that its complaining about are 100% there, so it has to be something to do with not closing a cursor or something and when the above loads its actually using the wrong cursor.
EDIT: Adding CursorLoader Code
public static final class VenueCursorLoader extends SimpleCursorLoader {
Context mContext;
public VenueCursorLoader(Context context) {
super(context);
mContext = context;
}
@Override
public Cursor loadInBackground() {
Cursor cursor = null;
VenuesDataSource datasource = new VenuesDataSource(mContext);
// TODO: provide the event_id to the getAllVenues method
cursor = datasource.getAllVenues(((EventActivity) mContext).getEventId());
if (cursor != null) {
cursor.getCount();
}
return cursor;
}
}
Any help much appreciated..
Basically everything you need to understand is outlined in the answer. There are several fixes you should make:
You should pass the CursorAdapter
a null
cursor to begin with. The LoaderManager
will have the CursorLoader
to perform the initial query for you. (see my answer above). Also note that the constructor you are currently using is deprecated. You should use this one instead (pass it 0
as the flag).
cursorAdapter = new SimpleCursorAdapter( getActivity(), R.layout.list_item, null, from, to, 0);
Remove this line:
getActivity().startManagingCursor(venuesCursor);
The whole point of the LoaderManager
is that it manages the cursor for you. You don't need to "hand the cursor to the system to manage"... that is exactly the job of the LoaderManager
. :)
Because of the reasons I described in #1 and #2, it looks like this line of code is unnecessary:
venuesCursor = getDatasource().getAllVenues(
((EventActivity) getActivity()).getEventId());
onItemClick
. Since you are using ListFragment
s, I suspect you want to be overriding onListItemClick
instead.I'm not sure why you have included these lines, but it looks like you want to remove them as well.
Cursor cursor = cursorAdapter.getCursor();
cursor.moveToPosition(position);
For the most part, you shouldn't manipulate the adapter's cursor, as it is managed by the internal system and is bound to the LoaderManager
.