大家好我想在我的代码中找出插入异常。在我开始之前,我开始插入字符串EditText,我想首先放入我自己的字符串。但是我从logcat收到错误。它们都是字符串类型,主键行也设置为自动增量。有没有人有任何指导。
数据库活动
private static class DbHelper extends SQLiteOpenHelper {
public DbHelper(Context context){
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE " + DATABASE_TABLE + " (" +
KEY_ROWID + " INTEGER PRIMARY KEY AUTOINCREMENT, " +
KEY_MODULECODE + " TEXT, " +
KEY_MODULENAME + " TEXT); "
);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// TODO Auto-generated method stub
db.execSQL("DROP TABEL IF EXISTS " + DATABASE_TABLE);
onCreate(db);
}
}
public database(Context c){
myContext = c;
}
public database openToWrite()throws SQLException{
myHelper = new DbHelper(myContext);
moduleDatabase = myHelper.getWritableDatabase();
return this;
}
public database openToRead()throws SQLException{
myHelper = new DbHelper(myContext);
moduleDatabase = myHelper.getReadableDatabase();
return this;
}
public void close(){
myHelper.close();
}
public void createEntry(String moduleCode, String moduleName) throws SQLException {
ContentValues cv = new ContentValues();
cv.put(KEY_MODULECODE,moduleCode);
cv.put(KEY_MODULENAME,moduleName);
moduleDatabase.insert(DATABASE_TABLE,null,cv);
// TODO Auto-generated method stub
}
public Cursor getData() {
String[] columns = new String [] {KEY_ROWID,KEY_MODULECODE, KEY_MODULENAME};
Cursor c = moduleDatabase.query(DATABASE_TABLE, columns, null, null, null, null, null);
return c;
}
}
主要活动
public class MyCourses extends Activity {
static final String TEST = "com.example.mycoursetimetable.TEST";
String [] MODULE;
database MODULEDATABASE;
ListView listContent;
Boolean didItWork;
Cursor cursor;
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_my_courses);
listContent =(ListView)findViewById(R.id.list);
MODULEDATABASE = new database(MyCourses.this);
MODULEDATABASE.openToWrite();
MODULEDATABASE.createEntry("TestCode", "TestName");
MODULEDATABASE.close();
MODULEDATABASE.openToRead();
cursor = MODULEDATABASE.getData();
MODULEDATABASE.close();
listContent = (ListView)findViewById(R.id.list);
TestCursorAdapter ca = new TestCursorAdapter(this, cursor, 0);
listContent.setAdapter(ca);
}
}
CursorAdatpter
public class TestCursorAdapter extends CursorAdapter {
private LayoutInflater viewInflater;
boolean didItWork;
public TestCursorAdapter(Context context, Cursor c, int flags) {
super(context, c, flags);
// TODO Auto-generated constructor stub
viewInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
@Override
public void bindView(View v, Context context, Cursor c)
{
TextView text_modulecode = (TextView)v.findViewById(R.id.labelModuleCode);
TextView text_modulename = (TextView)v.findViewById(R.id.labelEditModuleFull);
text_modulecode.setText(String.valueOf(c.getColumnIndex(database.KEY_MODULECODE)));
text_modulename.setText(String.valueOf(c.getColumnIndex(database.KEY_MODULENAME)));
}
@Override
public View newView(Context context, Cursor c, ViewGroup parent) {
View v = viewInflater.inflate(R.layout.listcourses, parent, false);
return v;
}
}
LogCat第80行引用moduleDatabase.insert(DATABASE_TABLE,null,cv);
10-21 22:42:19.812: E/Database(19591): Error inserting module_name=TestName module_code=TestCode
10-21 22:42:19.812: E/Database(19591): android.database.sqlite.SQLiteConstraintException: error code 19: constraint failed
10-21 22:42:19.812: E/Database(19591): at android.database.sqlite.SQLiteStatement.native_execute(Native Method)
10-21 22:42:19.812: E/Database(19591): at android.database.sqlite.SQLiteStatement.execute(SQLiteStatement.java:66)
10-21 22:42:19.812: E/Database(19591): at android.database.sqlite.SQLiteDatabase.insertWithOnConflict(SQLiteDatabase.java:1426)
10-21 22:42:19.812: E/Database(19591): at android.database.sqlite.SQLiteDatabase.insert(SQLiteDatabase.java:1286)
10-21 22:42:19.812: E/Database(19591): at com.example.mycoursetimetable.database.createEntry(database.java:80)
10-21 22:42:19.812: E/Database(19591): at com.example.mycoursetimetable.MyCourses.onCreate(MyCourses.java:48)
10-21 22:42:19.812: E/Database(19591): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
10-21 22:42:19.812: E/Database(19591): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2459)
10-21 22:42:19.812: E/Database(19591): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2512)
10-21 22:42:19.812: E/Database(19591): at android.app.ActivityThread.access$2200(ActivityThread.java:119)
10-21 22:42:19.812: E/Database(19591): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1863)
10-21 22:42:19.812: E/Database(19591): at android.os.Handler.dispatchMessage(Handler.java:99)
10-21 22:42:19.812: E/Database(19591): at android.os.Looper.loop(Looper.java:123)
10-21 22:42:19.812: E/Database(19591): at android.app.ActivityThread.main(ActivityThread.java:4363)
10-21 22:42:19.812: E/Database(19591): at java.lang.reflect.Method.invokeNative(Native Method)
10-21 22:42:19.812: E/Database(19591): at java.lang.reflect.Method.invoke(Method.java:521)
10-21 22:42:19.812: E/Database(19591): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:860)
10-21 22:42:19.812: E/Database(19591): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618)
10-21 22:42:19.812: E/Database(19591): at dalvik.system.NativeStart.main(Native Method)
10-21 22:42:19.862: E/Cursor(19591): Invalid statement in fillWindow()
答案 0 :(得分:2)
由于数据库设置不稳定,您得到了游标错误:Invalid statement in fillWindow()
。你关闭了数据库,实际上是两次,然后你将你关闭的数据库和因此不活动的光标附加到你的列表视图,似乎是对的?最佳实践通常表示您按顺序关闭光标然后关闭数据库对象。通常,您可以在查询完成后将它们放在任何位置,但是由游标适配器支持的列表视图是特殊的。列表视图打开并且您正在访问它的整个时间,您需要打开游标,以便数据源可用,就像任何数组对象或任何数据容器一样。否则,您将收到错误attempting to re-open an already-closed object
。因此,无论如何,当您的列表视图被消除时,放置它的最佳位置 imho 就在您的onDestroy()
方法中。
@Override
protected void onDestroy() {
super.onDestroy();
cursor.close();
MODULEDATABASE.close();
}
现在,我必须告诉你,我在同一个活动中打开了两个数据库实例。我可能会反对说这个,但.getWritableDatabase()
和.getReadableDatabase()
确实打开了相同的连接,它们并没有太大的不同。即使看起来很谨慎,关闭一个连接以打开另一个连接也不是一个好习惯。我不是说你应该完全从应用程序中删除一个方法(getReadable),但是在同一个活动生命周期中打开两个方法就是为花生而战。现在我们已经确定光标必须在活动的整个时间打开,这更是如此。好吧,既然我们正在谈论什么是必要的而不是,那么你实例化listContent
两次。
对于长篇解释感到抱歉,但我想确保细节已经清晰。