Android 游标错误 - “确保游标在访问数据之前正确初始化......”
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/10483644/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Android cursor error - "make sure cursor is initialized correctly before accessing data from it..."
提问by Barak
I've got an activity where a viewflipper shows a list containing the artists from mediastore, which onitem click display a list of albums by the chosen artist, which in turn displays the songs on that album. Once a song is clicked, it should populate a textview with the string 'title'.
我有一个活动,其中 viewflipper 显示一个包含来自 mediastore 的艺术家的列表,onitem 单击该列表显示所选艺术家的专辑列表,然后显示该专辑中的歌曲。单击歌曲后,它应该使用字符串“title”填充文本视图。
Until this point, all of the cursors are working fine, but the very last one seems to get put out of position somehow. Could anyone tell me why logcat is telling me:
到目前为止,所有游标都工作正常,但最后一个似乎以某种方式失去了位置。谁能告诉我为什么 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.
The particular row which cannot be read varies depending on which artist/album/song is chosen. The code is as follows. Thank you very much for your help.
无法读取的特定行因选择的艺术家/专辑/歌曲而异。代码如下。非常感谢您的帮助。
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);
}
}
}
}
回答by Barak
The problem isn't in the row, it's in the column.
问题不在行,而在列。
Couldn't read row 3, **col -1** from CursorWindow. Make sure the Cursor is initialized correctly before accessing data from it.
It's basically saying that your MediaColumns.TITLE column doesn't exist in the cursor. Which is true. It's not in your first cursor (the one that it is referencing). Your other cursors are all within if
statements so go out of scope and leave only the first one.
它基本上是说游标中不存在您的 MediaColumns.TITLE 列。这是真的。它不在您的第一个光标(它正在引用的那个)中。您的其他游标都在if
语句内,因此超出范围并只留下第一个。
You can either re-pull the cursor like you do in the other portions of the if
statement, or find some way to persist the cursor you got from the last if
statement.
您可以像在if
语句的其他部分那样重新拉动游标,也可以找到某种方法来保留从上一条if
语句获得的游标。
EDIT
编辑
It's pretty simple to fix, make the cursor a class variable. Also, I wouldn't keep re-using "cursor". Label them somethign individual and descriptive, it'll help you maintain readability in your code. I might do it like this:
修复非常简单,使光标成为类变量。另外,我不会继续重复使用“光标”。将它们标记为单独的和描述性的,这将帮助您保持代码的可读性。我可能会这样做:
public class MusicFlipper extends Activity implements OnItemClickListener {
private Cursor artistCursor;
private Cursor albumCursor;
Then you call them like you were but use the individual names.
然后你像以前一样称呼他们,但使用个人名称。
albumCursor = managedQuery(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
columns, where, whereVal, orderBy);
Since you declared it as a class variable it will be available through the whole class so in the last part you'd do:
由于您将其声明为类变量,因此在整个类中都可以使用它,因此在最后一部分中,您将执行以下操作:
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);
}
}