Ошибка курсора Android - убедитесь, что курсор правильно инициализирован, прежде чем обращаться к данным из него

У меня есть активность, в которой viewflipper показывает список, содержащий исполнителей из медиа-магазина, щелчок по которому отображает список альбомов выбранного исполнителя, который, в свою очередь, отображает песни в этом альбоме. Как только песня нажата, она должна заполнить текстовое представление строкой «название».

До этого момента все курсоры работали нормально, но самый последний, кажется, каким-то образом смещается. Может ли кто-нибудь сказать мне, почему logcat говорит мне:

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.

Конкретная строка, которую невозможно прочитать, зависит от выбранного исполнителя/альбома/песни. Код выглядит следующим образом. Большое спасибо за Вашу помощь.

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);

            }
        }
    }
}

person Community    schedule 07.05.2012    source источник
comment
Эй, timusus, если мой ответ поможет вам решить проблему, пожалуйста, нажмите на галочку рядом с ним, чтобы я получил признание, а все остальные знали, что ваша проблема была решена. Удачи!   -  person Barak    schedule 07.05.2012
comment
Барак, не могли бы вы увидеть комментарии ниже, я хотел бы получить немного больше информации о том, как достичь желаемого результата.   -  person    schedule 08.05.2012


Ответы (1)


Проблема не в строке, а в столбце.

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

В основном это говорит о том, что ваш столбец MediaColumns.TITLE не существует в курсоре. Что является правдой. Это не ваш первый курсор (тот, на который он ссылается). Все остальные ваши курсоры находятся внутри операторов if, поэтому выйдите за рамки и оставьте только первый.

Вы можете либо перетащить курсор, как в других частях оператора if, либо найти какой-то способ сохранить курсор, который вы получили из последнего оператора if.

ИЗМЕНИТЬ

Это довольно просто исправить, сделать курсор переменной класса. Кроме того, я бы не стал повторно использовать «курсор». Пометьте их чем-нибудь индивидуальным и описательным, это поможет вам поддерживать читабельность вашего кода. Я мог бы сделать это так:

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

Затем вы называете их, как раньше, но используете индивидуальные имена.

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

Поскольку вы объявили его как переменную класса, он будет доступен во всем классе, поэтому в последней части вы должны сделать:

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);
    }
}
person Barak    schedule 07.05.2012
comment
Спасибо за ответ Барак. Я обдумывал эту идею, но ничего не получается. Я даже перетащил курсор точно так же, как и в предыдущем операторе, но получаю ту же ошибку. Я думаю, это потому, что «позиция» изменилась. Не могли бы вы показать мне, как вы могли бы достичь этого? Спасибо. - person ; 08.05.2012
comment
Большое спасибо, Барак, очень признателен. - person ; 08.05.2012