-5

I'm creating an app right now for my final project in school which is a logger. The user stores info and the app saves it into a diary like entry. I've added values to be saved such as the title, date, and notes. Anything else added after that makes the app crash with the error:

Caused by: java.lang.IllegalStateException: Couldn't read row 0, col -1 from CursorWindow.  Make sure the Cursor is initialized correctly before accessing data from it.

I've double checked where all the code is written, there's no errors. The most confusing part about this is that I can get two other string values to store, but any additional ones added cause the app to crash.

There's 5 classes all connected to the database.

FitnessLab:


    private static ContentValues getContentValues(Fitness fitness) {
        ContentValues myContentValues = new ContentValues();
        myContentValues.put(FitnessDbSchema.FitnessTable.Columns.UUID, fitness.getId().toString());
        myContentValues.put(FitnessDbSchema.FitnessTable.Columns.TITLE, fitness.getTitle());
        myContentValues.put(FitnessDbSchema.FitnessTable.Columns.NOTES, fitness.getNotes());
        myContentValues.put(FitnessDbSchema.FitnessTable.Columns.CALORIES, fitness.getCalories());
        myContentValues.put(FitnessDbSchema.FitnessTable.Columns.WORKTIME, fitness.getworkTime());
        myContentValues.put(FitnessDbSchema.FitnessTable.Columns.DATE, fitness.getDate().getTime());

        return myContentValues;
    }

    private FitnessCursorWrapper queryFitnesss(String whereClause, String[] whereArgs) {

        Cursor cursor = mDatabase.query(
                FitnessDbSchema.FitnessTable.NAME,
                null,
                whereClause,
                whereArgs,
                null,
                null,
                null);


        return new FitnessCursorWrapper(cursor);
    }

FitnessFragment

 @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View v = inflater.inflate(R.layout.fragment_fitness, container, false);

        mTitleField = v.findViewById(R.id.fitness_title);
        mTitleField.setText(mFitness.getTitle());
        mTitleField.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence charSequence, int start, int count, int after) {

            }

            @Override
            public void onTextChanged(CharSequence charSequence, int start, int before, int count) {
                mFitness.setTitle(charSequence.toString());

            }

            @Override
            public void afterTextChanged(Editable s) {

            }
        });

        mNotesField = v.findViewById(R.id.fitness_notes);
        mNotesField.setText(mFitness.getNotes());
        mNotesField.addTextChangedListener(new TextWatcher() {

            @Override
            public void beforeTextChanged(CharSequence charSequence, int start, int count, int after) {

            }

            @Override
            public void onTextChanged(CharSequence charSequence, int start, int before, int count) {
                mFitness.setNotes(charSequence.toString());

            }

            @Override
            public void afterTextChanged(Editable charSequence) {

            }
        });

        mCaloriesField = v.findViewById(R.id.fitness_calories);
        mCaloriesField.setText(mFitness.getCalories());
        mCaloriesField.addTextChangedListener(new TextWatcher() {

            @Override
            public void beforeTextChanged(CharSequence charSequence, int start, int count, int after) {

            }

            @Override
            public void onTextChanged(CharSequence charSequence, int start, int before, int count) {
                mFitness.setCalories(charSequence.toString());

            }

            @Override
            public void afterTextChanged(Editable charSequence) {

            }
        });

        mWorkTimeField = v.findViewById(R.id.fitness_worktime);
        mWorkTimeField.setText(mFitness.getworkTime());
        mWorkTimeField.addTextChangedListener(new TextWatcher() {

            @Override
            public void beforeTextChanged(CharSequence charSequence, int start, int count, int after) {

            }

            @Override
            public void onTextChanged(CharSequence charSequence, int start, int before, int count) {
                mFitness.setworkTime(charSequence.toString());

            }

            @Override
            public void afterTextChanged(Editable charSequence) {

            }
        });

        mDateButton = v.findViewById(R.id.fitness_date);
        updateDate();

        mDateButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                FragmentManager manager = getFragmentManager();
                DatePickerFragment dialog = DatePickerFragment.newInstance(mFitness.getDate());
                dialog.setTargetFragment(FitnessFragment.this, REQUEST_DATE);
                dialog.show(manager, DIALOG_DATE);

            }
        });

FitnessBaseHelper

public class FitnessBaseHelper extends SQLiteOpenHelper {
    private static final int VERSION = 1;
    private static final String DATABASE_NAME = "fitnessBase.db";

    public FitnessBaseHelper(Context context) {
        super(context, DATABASE_NAME, null, VERSION);
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL("create table " + FitnessTable.NAME + "(" +
                " _id integer primary key autoincrement, " +
                FitnessTable.Columns.UUID + ", " +
                FitnessTable.Columns.TITLE + ", " +
                FitnessTable.Columns.NOTES + "," +
                FitnessTable.Columns.CALORIES + "," +
                FitnessTable.Columns.WORKTIME + "," +
                FitnessTable.Columns.DATE +
                ")"
        );

    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {

    }
}

FitnessCursorWrapper

public class FitnessCursorWrapper extends CursorWrapper {
    public FitnessCursorWrapper (Cursor cursor) {
        super(cursor);
    }

    public Fitness getFitness() {
        String uuidString = getString(getColumnIndex(FitnessDbSchema.FitnessTable.Columns.UUID));
        String title = getString(getColumnIndex(FitnessDbSchema.FitnessTable.Columns.TITLE));
        String notes = getString(getColumnIndex(FitnessDbSchema.FitnessTable.Columns.NOTES));
        String calories = getString(getColumnIndex(FitnessDbSchema.FitnessTable.Columns.CALORIES));
        String worktime = getString(getColumnIndex(FitnessDbSchema.FitnessTable.Columns.WORKTIME));
        long date = getLong(getColumnIndex(FitnessDbSchema.FitnessTable.Columns.DATE));

        Fitness fitness = new Fitness(UUID.fromString(uuidString));
        fitness.setTitle(title);
        fitness.setNotes(notes);
        fitness.setCalories(calories);
        fitness.setworkTime(worktime);
        fitness.setDate(new Date(date));

        return fitness;
    }

}

FitnessDbSchema

public class FitnessDbSchema {
    public static final class FitnessTable{
        public static final String NAME = "fitnesss";

        public static final class Columns{
            public static final String UUID = "uuid";
            public static final String TITLE = "title";
            public static final String NOTES = "notes";
            public static final String CALORIES = "calories";
            public static final String WORKTIME = "worktime";
            public static final String DATE = "date";
        }
    }

}

Error Log

2019-05-16 10:23:24.523 5543-5543/com.ctech.chloe.fitnesslog E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.ctech.chloe.fitnesslog, PID: 5543
    java.lang.RuntimeException: Unable to start activity ComponentInfo{com.ctech.chloe.fitnesslog/com.ctech.chloe.fitnesslog.FitnessListActivity}: java.lang.IllegalStateException: Couldn't read row 0, col -1 from CursorWindow.  Make sure the Cursor is initialized correctly before accessing data from it.
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2665)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2726)
        at android.app.ActivityThread.-wrap12(ActivityThread.java)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1477)
        at android.os.Handler.dispatchMessage(Handler.java:102)
        at android.os.Looper.loop(Looper.java:154)
        at android.app.ActivityThread.main(ActivityThread.java:6119)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776)
     Caused by: java.lang.IllegalStateException: Couldn't read row 0, col -1 from CursorWindow.  Make sure the Cursor is initialized correctly before accessing data from it.
        at android.database.CursorWindow.nativeGetString(Native Method)
        at android.database.CursorWindow.getString(CursorWindow.java:438)
        at android.database.AbstractWindowedCursor.getString(AbstractWindowedCursor.java:51)
        at android.database.CursorWrapper.getString(CursorWrapper.java:137)
        at com.ctech.chloe.fitnesslog.database.FitnessCursorWrapper.getFitness(FitnessCursorWrapper.java:19)
        at com.ctech.chloe.fitnesslog.FitnessLab.getFitnesss(FitnessLab.java:68)
        at com.ctech.chloe.fitnesslog.FitnessListFragment.updateUI(FitnessListFragment.java:85)
        at com.ctech.chloe.fitnesslog.FitnessListFragment.onCreateView(FitnessListFragment.java:43)
        at android.support.v4.app.Fragment.performCreateView(Fragment.java:2439)
        at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1460)
        at android.support.v4.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManager.java:1784)
        at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1852)
        at android.support.v4.app.BackStackRecord.executeOps(BackStackRecord.java:802)
        at android.support.v4.app.FragmentManagerImpl.executeOps(FragmentManager.java:2625)
        at android.support.v4.app.FragmentManagerImpl.executeOpsTogether(FragmentManager.java:2411)
        at android.support.v4.app.FragmentManagerImpl.removeRedundantOperationsAndExecute(FragmentManager.java:2366)
        at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:2273)
        at android.support.v4.app.FragmentManagerImpl.dispatchStateChange(FragmentManager.java:3273)
        at android.support.v4.app.FragmentManagerImpl.dispatchActivityCreated(FragmentManager.java:3229)
        at android.support.v4.app.FragmentController.dispatchActivityCreated(FragmentController.java:201)
        at android.support.v4.app.FragmentActivity.onStart(FragmentActivity.java:620)
        at android.support.v7.app.AppCompatActivity.onStart(AppCompatActivity.java:178)
        at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1248)
        at android.app.Activity.performStart(Activity.java:6696)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2628)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2726) 
        at android.app.ActivityThread.-wrap12(ActivityThread.java) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1477) 
        at android.os.Handler.dispatchMessage(Handler.java:102) 
        at android.os.Looper.loop(Looper.java:154) 
        at android.app.ActivityThread.main(ActivityThread.java:6119) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:886) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:776) 

I apologize if this is too much code posted here, but I honestly don't know what to do to fix this. My teacher is gone and I need to get the project done, but this error is setting me back quite a bit.

Zoe
  • 27,060
  • 21
  • 118
  • 148
  • https://stackoverflow.com/a/35042380/436938 – Sergey Glotov May 17 '19 at 14:15
  • This may be a duplicate of https://stackoverflow.com/questions/20240249/make-sure-the-cursor-is-initialized-correctly-before-accessing-data-from-it This particular answer may help: https://stackoverflow.com/a/37733727/6008271 To quote the response: > Try to position cursor by moveToFirst before reading data from it. > Check for null-> if (cursor != null && cursor.moveToFirst()) {} > Check for count-> (cursor != null && cursor.getCount() >0 && cursor.moveToFirst()){} – OscarVanL May 17 '19 at 13:47

1 Answers1

0

I've added values to be saved such as the title, date, and notes. Anything else added after that makes the app crash with the error

It makes me think you're using old database version now. You can check it by inspecting database. There are several ways to do it, described here: View contents of database file in Android Studio. Or you can check it by cleaning app data or uninstalling it (it will delete database from device).

Generally you should implement onUpgrade() method in your SQLiteOpenHelper to handle database schema changes.

By the way, it's a good practice to explicitly declare column types . You do it now only for _id column. Should be something like this (based on Fitness fields' types):

db.execSQL("create table " + FitnessTable.NAME + "(" +
            " _id integer primary key autoincrement, " +
            FitnessTable.Columns.UUID + " TEXT , " +
            FitnessTable.Columns.TITLE + " TEXT, " +
            FitnessTable.Columns.NOTES + " TEXT, " +
            FitnessTable.Columns.CALORIES + " TEXT, " + 
            FitnessTable.Columns.WORKTIME + " TEXT, " +
            FitnessTable.Columns.DATE + " INTEGER " +
            ")"
Sergey Glotov
  • 20,200
  • 11
  • 84
  • 98