hoping someone can help me figure this issue out. I'm trying to build an app in Android Studio for school and am running into an issue when trying to get it to load results from a database using a cursor. I keep getting the error message that the cursor is initialized at -1 and it can't access column 0. Any ideas what might be causing it? Code is below along with error message:
Main Activity:
package com.example.lab2;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Context;
import android.database.Cursor;
import android.graphics.Color;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Adapter;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.Switch;
import android.widget.TextView;
import android.widget.Toast;
import java.util.ArrayList;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button btn = findViewById(R.id.the_button);
EditText input = findViewById(R.id.edittext);
Switch urgent = findViewById(R.id.the_switch);
dbOpener dbOpener = new dbOpener(MainActivity.this);
Cursor cursor;
ListView thisList = (ListView) findViewById(R.id.listview);
AlertDialog.Builder alertDIalogBuilder = new AlertDialog.Builder(this);
ArrayList<toDoItem> arrayList = new ArrayList<toDoItem>();
class MyAdapter extends BaseAdapter {
private Context context;
private ArrayList<toDoItem> items;
public MyAdapter(Context context, ArrayList<toDoItem> items) {
this.context = context;
this.items = items;
}
@Override
public int getCount() {
return arrayList.size();
}
@Override
public Object getItem(int position) {
return arrayList.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View mainView = LayoutInflater.from(context).inflate(R.layout.activity_main_todolayout, parent, false);
LayoutInflater inflater = getLayoutInflater();
if(mainView == null) {
mainView = inflater.inflate(R.layout.activity_main_todolayout, parent, false);
}
TextView itemView = mainView.findViewById(R.id.to_do_items);
itemView.setText((arrayList.get(position).getToDoName().toString()));
if(arrayList.get(position).geturgent() == true) {
mainView.setBackgroundColor(Color.RED);
itemView.setTextColor(Color.WHITE);
}
return mainView;}
};
MyAdapter adapter = new MyAdapter(this, arrayList);
thisList.setAdapter(adapter);
urgent.setChecked(false);
urgent.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View V) {
urgent.setChecked(true);
}
});
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String holder = input.getText().toString();
arrayList.add (new toDoItem(holder, urgent.isChecked()));
input.getText().clear();
adapter.notifyDataSetChanged();
int urgentStatus = 0;
if(urgent.isChecked() == true) {
urgentStatus = 1;
} else {
urgentStatus = 0;
}
dbOpener.addItem(holder, urgentStatus);
urgent.setChecked(false);
}
});
thisList.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
@Override
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
String title = getString(R.string.alert_dialogue_title);
String message = getString(R.string.alert_dialogue_message);
String pos_button = getString(R.string.pos_button);
String neg_button = getString(R.string.neg_button);
alertDIalogBuilder.setTitle(title);
alertDIalogBuilder.setMessage(message " " position);
alertDIalogBuilder.setPositiveButton(pos_button, (click, arg) -> {
arrayList.remove(position);
adapter.notifyDataSetChanged();
});
alertDIalogBuilder.setNegativeButton(neg_button, (click, arg) -> {
});
alertDIalogBuilder.create();
alertDIalogBuilder.show();
return false;
}
});
cursor = dbOpener.readData();
int nameColIndex = cursor.getColumnIndex("COL_ITEM_NAME");
int urgentColIndex = cursor.getColumnIndex("COL_URGENT");
int idColIndex = cursor.getColumnIndex("COL_ID");
for(int i = 0; i < cursor.getCount(); i ) {
String name = cursor.getString(nameColIndex);
int urgentHolder = cursor.getInt(urgentColIndex);
long id = cursor.getLong(idColIndex);
boolean converter = false;
if(urgentHolder == 1) {
converter = true;
} else {
converter = false;
}
arrayList.add(new toDoItem(name, converter));
}
}
}
Database Opener:
package com.example.lab2;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.widget.Toast;
public class dbOpener extends SQLiteOpenHelper {
protected final static String DATABASE_NAME = "toDoListDB";
protected final static int VERSION_NUM = 1;
public final static String TABLE_NAME = "TO_DO_ITEMS";
public final static String COL_ITEM_NAME = "ITEM";
public final static String COL_URGENT = "URGENT";
public final static String COL_ID = "_id";
private Context ctx;
String [] columns = {dbOpener.COL_ITEM_NAME, dbOpener.COL_ITEM_NAME, dbOpener.COL_URGENT};
public dbOpener(Context ctx) {super(ctx, DATABASE_NAME, null, VERSION_NUM);
this.ctx = ctx;
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE " TABLE_NAME " (_id INTEGER PRIMARY KEY AUTOINCREMENT, " COL_ITEM_NAME
" TEXT," COL_URGENT " INTEGER)");
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS " TABLE_NAME);
onCreate(db);
}
void addItem(String itemName, int urgent) {
SQLiteDatabase db = this.getWritableDatabase();
ContentValues cnt = new ContentValues();
cnt.put(COL_ITEM_NAME, itemName);
cnt.put(COL_URGENT, urgent);
long result = db.insert(TABLE_NAME, null, cnt);
if(result == -1) {
Toast.makeText(ctx, "Failure", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(ctx, "Success", Toast.LENGTH_SHORT).show();
}
}
Cursor readData() {
SQLiteDatabase db = this.getReadableDatabase();
Cursor results = db.rawQuery("SELECT * from " TABLE_NAME, null);
return results;
}
}
Error message:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.lab2, PID: 15645
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.lab2/com.example.lab2.MainActivity}: android.database.CursorIndexOutOfBoundsException: Index -1 requested, with a size of 3
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2913)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3048)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1808)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6669)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
Caused by: android.database.CursorIndexOutOfBoundsException: Index -1 requested, with a size of 3
at android.database.AbstractCursor.checkPosition(AbstractCursor.java:468)
at android.database.AbstractWindowedCursor.checkPosition(AbstractWindowedCursor.java:136)
at android.database.AbstractWindowedCursor.getString(AbstractWindowedCursor.java:50)
at com.example.lab2.MainActivity.onCreate(MainActivity.java:152)
at android.app.Activity.performCreate(Activity.java:7136)
at android.app.Activity.performCreate(Activity.java:7127)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1271)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2893)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3048)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:78)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1808)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6669)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
I/Process: Sending signal. PID: 15645 SIG: 9
Disconnected from the target VM, address: 'localhost:49568', transport: 'socket'
CodePudding user response:
You've defined your schema with these constants:
public final static String TABLE_NAME = "TO_DO_ITEMS";
public final static String COL_ITEM_NAME = "ITEM";
public final static String COL_URGENT = "URGENT";
public final static String COL_ID = "_id";
But you're using the names of the constants here rather than their values:
int nameColIndex = cursor.getColumnIndex("COL_ITEM_NAME");
int urgentColIndex = cursor.getColumnIndex("COL_URGENT");
int idColIndex = cursor.getColumnIndex("COL_ID");
In other words, in MainActivity
, do this:
int nameColIndex = cursor.getColumnIndex(dbOpener.COL_ITEM_NAME);
int urgentColIndex = cursor.getColumnIndex(dbOpener.COL_URGENT);
int idColIndex = cursor.getColumnIndex(dbOpener.COL_ID);
Also, classes start with capital letters. You should rename dbOpener
to DbOpener
.
CodePudding user response:
In your cursor-reading for
loop, you need to move the cursor in order to iterate over the result set. An easy fix there would be to change
for(int i = 0; i < cursor.getCount(); i ) {
to
while(cursor.moveToNext()) {
There are other issues in your code such as the one pointed out by Gavin Wright in his answer. Missing moveTo...()
is the reason for the crash you've reported.