Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Multiple Loaders with LoaderManager, not getting right Loader

I have two loaders, one to populate bind returned data to 2 TextViews and another to populate a ListView. How do I make sure the correct loader loads for each situation? I am getting an error in the where first loader (WR_VIEW case) doesn't seem to be created or loading so in the onLoadFinished() it returns a "No such column found error" because it is accessing the second loader which doesn't call that column.

Here in my onCreate method I set up the adapter for the list view:

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.workouts_options);

    String[] uiBindFrom = { ExerciseTable.COLUMN_NAME };
    int[] uiBindTo = { R.id.text1 };

    SimpleCursorAdapter adapter = new SimpleCursorAdapter(
        getApplicationContext(), 
        R.layout.exercises_row, 
        null, 
        uiBindFrom, 
        uiBindTo,
        CursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);    

    final ListView lv = (ListView) findViewById(android.R.id.list);

    lv.setAdapter(adapter);
    lv.setEmptyView(findViewById(android.R.id.empty));
    lv.setClickable(true);
    lv.setOnItemClickListener(new AdapterView.OnItemClickListener() {
        @Override
        public void onItemClick(AdapterView<?> arg0, View arg1, int position, long id) {
        }
    });

    getSupportLoaderManager().initLoader(WR_VIEW, null, this);
    getSupportLoaderManager().initLoader(EXERCISE_VIEW, null, this);
}

Create my 2 different CursorLoaders:

    public Loader<Cursor> onCreateLoader(int id, Bundle args) {         
        switch(id) {
            case WR_VIEW:
                String[] projection = { WorkoutRoutineTable.COLUMN_ID, WorkoutRoutineTable.COLUMN_NAME, WorkoutRoutineTable.COLUMN_DESCRIPTION };    
                return new CursorLoader(this, Workouts.buildWorkoutIdUri(""+mRowId), projection, null, null, null);
            default:
                String[] columns = {ExercisesColumns.NAME, WRExercisesColumns.COLUMN_ID };          
                return new CursorLoader(this, Workouts.buildWorkoutIdExerciseUri(""+mRowId), columns, null, null, null);
        }
    }

Bind data to my TextViews here and swapCursor for the ListView:

public void onLoadFinished(Loader<Cursor> loader, Cursor cursor) {
    int id = loader.getId();
    switch(id) {
        case WR_VIEW: 
            if (cursor != null && cursor.moveToFirst()) {
                mNameText.setText(cursor.getString(cursor.getColumnIndexOrThrow(WorkoutRoutineTable.COLUMN_NAME)));
                mDescriptionText.setText(cursor.getString(cursor.getColumnIndexOrThrow(WorkoutRoutineTable.COLUMN_DESCRIPTION)));

                getSupportActionBar().setTitle(mNameText.getText());
                if (!TextUtils.isEmpty(mDescriptionText.getText())) {
                    getSupportActionBar().setSubtitle(mDescriptionText.getText());
                }
                cursor.close(); 
            }
        default:
            adapter.swapCursor(cursor);
        }
    }

Resetting the Loader:

public void onLoaderReset(Loader<Cursor> loader) {
    int id = loader.getId();
    switch(id) {
        case WR_VIEW: 
            break;
        default:
            adapter.swapCursor(null);
            break;
    }
}
like image 603
jocey Avatar asked Jul 13 '12 02:07

jocey


1 Answers

In your onLoadFinished() you don't have a break after WR_VIEW case, so the default clause is getting run as well, passing the wrong cursor to your adapter. (onCreateLoader seems to have a similar issue as well)

like image 98
superfell Avatar answered Oct 11 '22 11:10

superfell