如何修复SQLite:无法从游标窗口中读取行0,列-1

时间:2019-05-17 13:24:14

标签: java android android-sqlite

我现在正在为学校的最后一个项目(即记录器)创建一个应用程序。用户存储信息,应用程序将其保存到日记条目中。我添加了要保存的值,例如标题,日期和注释。之后添加的任何其他内容都会使应用程序崩溃,并显示以下错误:

class ViewController: UIViewController {

    @IBOutlet var widthConstaint: NSLayoutConstraint!
    @IBOutlet var tableView: UITableView!
    @IBOutlet var watchContainerView: UIView!

    override func viewDidLoad() {
        super.viewDidLoad()
        start()
    }

    func start() {
        DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
            if self.widthConstaint.constant == 50 {
                self.change(width: 100)
            } else {
                self.change(width: 50)
            }
            self.start()
        }
    }

    func change(width: CGFloat) {
        widthConstaint.constant = width
        UIView.animate(withDuration: 1.0) {
            self.view.layoutIfNeeded()
        }   
    }
}

extension ViewController: UITableViewDataSource {
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {   
        let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
        return cell
    }
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 300
    }

}

我仔细检查了所有代码的编写位置,没有错误。对此最令人困惑的部分是,我可以存储另外两个字符串值,但是添加的任何其他字符串值都会导致应用程序崩溃。

有5个类都连接到数据库。

健身实验室:

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.

健身片段


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

FitnessBaseHelper

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

            }
        });

FitnessCursorWrapper

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

    }
}

FitnessDbSchema

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

}

错误日志

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";
        }
    }

}

很抱歉,如果此处发布的代码过多,但老实说,我不知道该如何解决。我的老师不在了,我需要完成项目,但是这个错误使我退缩了很多。

1 个答案:

答案 0 :(得分:2)

  

我添加了要保存的值,例如标题,日期和便笺。此后添加的所有内容都会使应用程序崩溃并显示错误

这让我觉得您现在正在使用旧数据库版本。您可以通过检查数据库进行检查。可以通过以下几种方法来做到这一点:View contents of database file in Android Studio。或者,您可以通过清除应用程序数据或将其卸载来检查它(它将从设备中删除数据库)。

通常,您应该在SQLiteOpenHelper中实现onUpgrade()方法以处理数据库架构更改。

顺便说一句,明确声明列类型是一个好习惯。现在,您仅对_id列执行此操作。应该是这样的(基于Fitness字段的类型):

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 " +
            ")"