cannot inflate fragment as I'm getting the mentioned error:'java.lang.IllegalStateException: Couldn't read row 0, col -1 from CursorWindow. Make sure the Cursor is initialized correctly before accessing data from it.'this is the method I'm trying to override:
fun Context.fetchItems() : MutableList<MyItem> {
val items = mutableListOf<MyItem>()
val cursor = contentResolver.query(MY_PROVIDER_CONTENT_URI,
null, null, null, null)
while (cursor != null && cursor.moveToNext()) {
items.add(
MyItem(
cursor.getLong(cursor.getColumnIndex(MyItem::id.name)),
cursor.getString(cursor.getColumnIndex(MyItem::name.name)),
cursor.getString(cursor.getColumnIndex(MyItem::status.name)),
cursor.getString(cursor.getColumnIndex(MyItem::species.name)),
cursor.getString(cursor.getColumnIndex(MyItem::type.name)),
cursor.getString(cursor.getColumnIndex(MyItem::gender.name)),
cursor.getString(cursor.getColumnIndex(MyItem::origin.name)),
cursor.getString(cursor.getColumnIndex(MyItem::location.name)),
cursor.getString(cursor.getColumnIndex(MyItem::image.name)),
cursor.getString(cursor.getColumnIndex(MyItem::url.name)),
cursor.getString(cursor.getColumnIndex(MyItem::created.name)),
cursor.getInt(cursor.getColumnIndex(MyItem::read.name)) == 1
)
)
}
return items
}
table creation:
private const val DB_NAME = "myItems.db"
private const val DB_VERSION = 1
private const val TABLE_NAME = "myitems"
private val CREATE_TABLE = "create table $TABLE_NAME( "
"${MyItem::id.name} integer primary key autoincrement, "
"${MyItem::name.name} text not null, "
"${MyItem::status.name} text not null, "
"${MyItem::species.name} text not null, "
"${MyItem::type.name} text not null, "
"${MyItem::gender.name} text not null, "
"${MyItem::origin.name} text not null, "
"${MyItem::location.name} text not null, "
"${MyItem::image.name} text not null, "
"${MyItem::url.name} text not null, "
"${MyItem::created.name} text not null, "
"${MyItem::read.name} integer not null"
")"
private const val DROP_TABLE = "drop table $TABLE_NAME"
class I'm trying to use:
data class CharacterItem(
@SerializedName("id") var id: Int? = null,
@SerializedName("name") var name: String? = null,
@SerializedName("status") var status: String? = null,
@SerializedName("species") var species: String? = null,
@SerializedName("type") var type: String? = null,
@SerializedName("gender") var gender: String? = null,
@SerializedName("origin") var origin: String? = null,
@SerializedName("location") var location: String? = null,
@SerializedName("image") var image: String? = null,
@SerializedName("url") var url: String? = null,
@SerializedName("created") var created: String? = null
)
this is the api I'm trying to get it from:
https://rickandmortyapi.com/api/character/1,183
Sorry if something's unclear english is my third language.
https://rickandmortyapi.com/api/character/1,183
So,I'm learning kotlin and trying to get data from json into sqlLite and onto a fragment to show on screen.
CodePudding user response:
The Isssue
The col -1 is due to the getColumnIndex method not finding the specified column (column name not found in the cursor's list of output columns).
From the message, as it specifies row 0 (the first row) the Cursor has been successfully populated with at least 1 row.
Possible Cause
At a guess, you have amended the table by adding a column but that the table itself has not been changed.
Just changing CREATE_TABLE to add/remove/alter the table will not change the table. As the onCreate method of the class that extends SQLiteOpenHelper is only ever called once for the lifetime of the database. The method is not called every time the App is run.
- The assumption is that the parameters being passed to the contentResolver's query method is passing null for the columns in the SQliteDatabase's query method and thus you are extracting all columns. If not then it may just be that you have omitted the said column from the list of columns to retrieve into the Cursor.
Fixing the potential cause
If you can afford to lose existing data then the simple fix is to uninstall the app and to rerun. The uninstall will delete the database (ending it's life) and thus result in the onCreate method running and creating the database and the changed table.
If you have data that you cannot afford to lose then you will need to ALTER the table accordingly. You can do this via the onUpdate method in conjunction with increasing the value of DB_VERSION.
Additonal
A Cursor returned from any of the SQLite API methods will never be null, so there is no need to check for null. If a Cursor is empty then the Cursor will simply reflect that there are no rows and the moveToNext method (as well as most other move???? methods) will return false.
As such the check for null is redundant.
As such instead of while (cursor != null && cursor.moveToNext()) {
you can use the simpler while (cursor.moveToNext()) {