Error de cursor Android: "asegúrese de que el cursor se inicialice correctamente antes de acceder a los datos de él …"

Tengo una actividad donde un viewflipper muestra una lista que contiene a los artistas de mediastore, que clic en el clic mostrar una lista de álbumes por el artista elegido, que a su vez muestra las canciones de ese álbum. Una vez que se hace clic en una canción, se debe rellenar una textview con la cadena 'title'.

Hasta este punto, todos los cursores están funcionando bien, pero el último parece estar fuera de posición de alguna manera. ¿Podría alguien decirme por qué logcat me está diciendo:

05-07 23:58:54.195: E/AndroidRuntime(1961): java.lang.IllegalStateException: Couldn't read row 3, col -1 from CursorWindow. Make sure the Cursor is initialized correctly before accessing data from it. 

La fila particular que no se puede leer varía dependiendo de qué artista / álbum / canción se elige. El código es el siguiente. Muchas gracias por su ayuda.

 package music.flipper; import android.app.Activity; import android.database.Cursor; import android.os.Bundle; import android.provider.BaseColumns; import android.provider.MediaStore; import android.provider.MediaStore.Audio.AlbumColumns; import android.provider.MediaStore.Audio.ArtistColumns; import android.provider.MediaStore.Audio.AudioColumns; import android.provider.MediaStore.MediaColumns; import android.view.View; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; import android.widget.ListView; import android.widget.SimpleCursorAdapter; import android.widget.TextView; import android.widget.ViewFlipper; public class MusicFlipper extends Activity implements OnItemClickListener { /** Called when the activity is first created. */ ViewFlipper viewflipper; Cursor cursor; private String currentList = "Artist"; @SuppressWarnings("deprecation") @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.flipper); //set the main view to flipper. viewflipper = (ViewFlipper) findViewById(R.id.viewFlipper1); String[] columns = { BaseColumns._ID, ArtistColumns.ARTIST }; //The columns to return for each row. cursor = managedQuery(MediaStore.Audio.Artists.EXTERNAL_CONTENT_URI, columns, null, null, null); ListView listView = (ListView) findViewById(R.id.listView1); listView.setOnItemClickListener(this); //set an onitemclicklistener to the first listview in flipper String[] displayFields = new String[] { ArtistColumns.ARTIST }; //set all the artist names to the array 'displayfields' int[] displayViews = new int[] { R.id.rowItem }; //number of rows to display and where to bind them SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, R.layout.row_item, cursor, displayFields, displayViews); listView.setAdapter(adapter); } //Take the display fields array, and bind to the matching display row @SuppressWarnings("deprecation") public void onItemClick(AdapterView<?> a, View v, int position, long id) { if( currentList.equals("Artist")) { if (cursor.moveToPosition(position)) { //once an item is clicked, move the cursor to that items position String where = AudioColumns.ARTIST + "=?"; // Have the cursor look within the artist row? String whereVal[] = { cursor.getString(cursor .getColumnIndex(AlbumColumns.ARTIST)) }; //Choose the particular row with the chosen artist's name String[] columns = { BaseColumns._ID, AudioColumns.ALBUM, }; String orderBy = BaseColumns._ID; cursor = managedQuery(MediaStore.Audio.Albums.EXTERNAL_CONTENT_URI, columns, where, whereVal, orderBy); ListView listView = (ListView) findViewById(R.id.listView2); listView.setOnItemClickListener(this); String[] displayFields = new String[] { AudioColumns.ALBUM }; int[] displayViews = new int[] { R.id.rowItem }; SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, R.layout.row_item, cursor, displayFields, displayViews); listView.setAdapter(adapter); currentList = "Album"; viewflipper.showNext();} } if (currentList.equals("Album")) { if (cursor.moveToPosition(position)) { String where = AudioColumns.ALBUM + "=?"; String whereVal[] = { cursor.getString(cursor .getColumnIndex(AlbumColumns.ALBUM)) }; String[] columns = { MediaColumns.DATA, BaseColumns._ID, MediaColumns.TITLE, MediaColumns.DISPLAY_NAME, MediaColumns.MIME_TYPE, }; String orderBy = MediaColumns.TITLE; cursor = managedQuery(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, columns, where, whereVal, orderBy); ListView listView = (ListView) findViewById(R.id.listView3); listView.setOnItemClickListener(this); String[] displayFields = new String[] { MediaColumns.TITLE }; int[] displayViews = new int[] { R.id.rowItem }; SimpleCursorAdapter adapter = new SimpleCursorAdapter(this, R.layout.row_item, cursor, displayFields, displayViews); listView.setAdapter(adapter); currentList.equals("Songs"); viewflipper.showNext();} } if (currentList.equals("Songs")) { if (cursor.moveToPosition(position)) { String title = cursor.getString(cursor.getColumnIndex(MediaColumns.TITLE)); TextView myTextView = (TextView) findViewById(R.id.title); myTextView.setText(title); } } } } 

El problema no está en la fila, está en la columna.

 Couldn't read row 3, **col -1** from CursorWindow. Make sure the Cursor is initialized correctly before accessing data from it. 

Básicamente dice que su columna MediaColumns.TITLE no existe en el cursor. Cual es verdad. No está en su primer cursor (el que está haciendo referencia). Sus otros cursores están dentro de las declaraciones, así que salga del alcance y deje solo el primero.

Puede volver a tirar del cursor como lo hace en las otras partes de la sentencia if , o encontrar alguna manera de persistir el cursor que obtuvo de la última declaración if .

EDITAR

Es bastante simple de arreglar, hacer que el cursor sea una variable de clase. Además, no volvería a usar "cursor". Etiquetarlos somethign individual y descriptivo, le ayudará a mantener la legibilidad en su código. Podría hacerlo así:

 public class MusicFlipper extends Activity implements OnItemClickListener { private Cursor artistCursor; private Cursor albumCursor; 

Entonces usted los llama como usted era pero utiliza los nombres individuales.

 albumCursor = managedQuery(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, columns, where, whereVal, orderBy); 

Dado que lo declaró como una variable de clase, estará disponible en toda la clase, así que en la última parte que haría:

 if (currentList.equals("Songs")) { if (albumCursor.moveToPosition(position)) { String title = albumCursor.getString(albumCursor.getColumnIndex(MediaColumns.TITLE)); TextView myTextView = (TextView) findViewById(R.id.title); myTextView.setText(title); } } 
  • Cómo cargar imágenes de la URL en el widget de la aplicación Android?
  • Cómo inflar correctamente un diseño con un ViewFlipper anidado?
  • Actualizar altura con ViewFlipper
  • Creación de un ViewFlipper como la pantalla de inicio con MotionEvent.ACTION_MOVE
  • El valor en edittext no se muestra hasta que se enfoque. Androide
  • Problema de superposición de texto en ViewFlipper ..
  • Cómo cambiar entre actividades con viewflipper
  • Android Cómo llamar a OnFling cuando Swiping en cualquier lugar de la actividad no sólo en el ViewFlipper
  • Cómo agregar mediante programación varios LinearLayouts en una vista y, a continuación, agregar a ViewFlipper?
  • ¿La mejor práctica para viewflipper que contiene 10 linearlayouts?
  • Android: el diseño de inflado toma mucho tiempo
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.