我现在正在为学校的最后一个项目(即记录器)创建一个应用程序。用户存储信息,应用程序将其保存到日记条目中。我添加了要保存的值,例如标题,日期和注释。之后添加的任何其他内容都会使应用程序崩溃,并显示以下错误:
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";
}
}
}
很抱歉,如果此处发布的代码过多,但老实说,我不知道该如何解决。我的老师不在了,我需要完成项目,但是这个错误使我退缩了很多。
答案 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 " +
")"