我对SQLite DB有疑问。我创建了一个带有列表视图的活动,以便在单击项目时显示下一个活动。这是应用程序启动时首先显示的主要活动。活动是这样的,在初始化期间,它会在表中插入值。 DB中的表具有包含主键和唯一字段的字段。我已将字段声明为唯一字段,以便重复字段不会在下一行中添加。只是它应该避免在新行中插入相同的值。 值的初始化和插入在第一个活动本身的onCreate中声明。但是这里出现的问题是,当这个应用程序关闭并再次打开时,它会在Logcat中写入错误消息,"错误在ButterflyDB"中插入值。我知道这个问题出现了bcoz已经有一个数据库,并且字段被声明为唯一。此外,在第一个活动中调用插入函数时,显示活动需要花费大量时间。经过几个时间延迟后,第一个屏幕出现bcoz,应用程序每次出现第一个屏幕时都会在数据库中插入值。
我的代码如下:
package com.myambitionconsultants.butterflyworld;
import android.app.ListActivity;
import android.content.ContentValues;
import android.content.Intent;
import android.database.Cursor;
import android.database.SQLException;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;
public class ButterflyWorldActivity extends ListActivity {
private static final String TAG = ButterflyWorldActivity.class.getSimpleName();
/**
* Declare the variables and objects.
* ButterflyDBAdapter - To initialize the DB, create the tables and store the values in it.
* ImageIDStorage - To store the Image drawable IDs into the table.
* String[], int[] - To access the arrays declared in the data.xml file.
* String - SQL statements to run when this activity is displayed.
* Cursor - To access the records in the row of the table to display.
*/
ButterflyDBAdapter dbAdapter;
ImageIDStorage imgIDStorage;
ButterflyDetailsStorage detailsStorage;
String[] levels, butterfly_common_names, butterfly_scientific_names, image_path, cat_id;
int [] drawableID;
int [] butterfly_id;
String sql_butterfly_cat, sql_drawable_id;
Cursor cur;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
/**
* Initialize the declared variables.
* dbAdapter - Initialize with ButterflyDBAdapter object.
* imgIDStorage - Initialize with ImageIDStorage object.
*
* levels, butterfly_common_names, butterfly_scientific_names, image_path, butterfly_id, cat_id
* - Use the getStringArray() method to load each and every value from the XML.
*/
dbAdapter = new ButterflyDBAdapter(this);
imgIDStorage = new ImageIDStorage(this);
detailsStorage = new ButterflyDetailsStorage(this);
dbAdapter.createTable();
levels = getResources().getStringArray(R.array.butterfly_categories);
butterfly_common_names = getResources().getStringArray(R.array.butterfly_common_names);
butterfly_scientific_names = getResources().getStringArray(R.array.butterfly_scientific_names);
//image_path = getResources().getStringArray(R.array.image_path);
butterfly_id = getResources().getIntArray(R.array.butterfly_id);
cat_id = getResources().getStringArray(R.array.category_id);
//drawables = getResources().getStringArray(R.array.drawable_array);
/**
* Method Calls.
* Insert the Butterfly Categories, Butterflies, ImageIDs in the database.
*/
insertButterflyCategory();
insertButterfly();
imgIDStorage.insertImageID_1();
imgIDStorage.insertImageID_2();
detailsStorage.insertButterflyDetails();
/**
* SQL statement to select the Category Name from the ButterflyCategory Table.
* Initialize the cursor to execute the query from the table.
*/
sql_butterfly_cat = "Select " + ButterflyDBAdapter.COL_CATEGORY_NAME + " from " + ButterflyDBAdapter.BUTTERFLY_CATEGORY;
cur = dbAdapter.getSQLiteDB().rawQuery(sql_butterfly_cat, null);
/**
* After retrieving the rows from the cursor, store the category name values in the array.
* Move the cursor to the first.
* Till the last row value in the table, keep on adding the category names in the array.
*/
//After retrieving the rows from the cursor, store the category name values in the array.
String[] category = new String[cur.getCount()];
Log.i(TAG, "Count: " + cur.getCount());
cur.moveToFirst(); //Move the cursor to the first row.
for(int i = 0; i < cur.getCount(); i++){
//Till the last row value in the table, keep on adding the category names in the array.
category[i] =cur.getString(cur.getColumnIndex(ButterflyDBAdapter.COL_CATEGORY_NAME));
//Move the cursor to the next row
cur.moveToNext();
}
/**
* Use the setListAdapter() method to display the category names in the list.
*/
setListAdapter(new ArrayAdapter<String>(this, R.layout.list_item, category));
/**
* Use the getListView() method.
*/
ListView lv = getListView();
lv.setTextFilterEnabled(true);
/**
* Manage the cursor
*/
startManagingCursor(cur);
/**
* Determine which category was clicked in the list.
* Pass the category name as extra in the bundle.
* Display the next activity with the values passed through the bundle.
*/
lv.setOnItemClickListener(new OnItemClickListener() {
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
String category_name = ((TextView) view).getText().toString();
Intent i = new Intent(ButterflyWorldActivity.this, ShowCategory.class);
//Intent i2 = new Intent(ButterflyWorldActivity.this, .class);
i.putExtra("category_name", category_name);
Bundle bundle = new Bundle();
switch(position){
case 0:
bundle.putString("category_name", category_name);
//bundle.putInt("drawable1", R.drawable.tailed_jay_1);
//bundle.putInt("drawable2", R.drawable.blue_bottle_1);
//bundle.putInt("drawable3", R.drawable.common_raven_1);
i.putExtras(bundle);
startActivity(i);
break;
case 1:
bundle.putString("category_name", category_name);
//bundle.putInt("drawable1", R.drawable.common_wanderer_1);
//bundle.putInt("drawable2", R.drawable.common_jezabel_1);
//bundle.putInt("drawable3", R.drawable.psyche_1);
i.putExtras(bundle);
startActivity(i);
break;
case 2:
bundle.putString("category_name", category_name);
//bundle.putInt("drawable1", R.drawable.common_silverline_1);
//bundle.putInt("drawable2", R.drawable.grass_jewel_1);
//bundle.putInt("drawable3", R.drawable.monkey_puzzle_1);
i.putExtras(bundle);
startActivity(i);
break;
case 3:
bundle.putString("category_name", category_name);
//bundle.putInt("drawable1", R.drawable.leopard_1);
//bundle.putInt("drawable1", R.drawable.common_silverline_1);
//bundle.putInt("drawable2", R.drawable.peacock_pansy_1);
//bundle.putInt("drawable3", R.drawable.blue_oakleaf_1);
i.putExtras(bundle);
startActivity(i);
break;
case 4:
bundle.putString("category_name", category_name);
//bundle.putInt("drawable1", R.drawable.chestnut_bob_1);
//bundle.putInt("drawable2", R.drawable.golden_angle_1);
//bundle.putInt("drawable3", R.drawable.grass_demon_1);
//bundle.putInt("drawable3", R.drawable.psyche_1);
i.putExtras(bundle);
startActivity(i);
break;
}
}
});
}
/**
* Insert the butterfly category names into the database.
* The number of values in the levels[] determines the number of
* rows to be put in the ButterflyCategory table.
*/
public void insertButterflyCategory(){
for(int i = 0; i<levels.length;i++){
ContentValues cv = new ContentValues();
//cv.put(ButterflyDBAdapter.COL_CATEGORY_ID, i+1);
cv.put(ButterflyDBAdapter.COL_CATEGORY_NAME, levels[i]);
try{
dbAdapter.getSQLiteDB().insert(ButterflyDBAdapter.BUTTERFLY_CATEGORY, null, cv);
//dbAdapter.getSQLiteDB().insertWithOnConflict(ButterflyDBAdapter.BUTTERFLY_CATEGORY, null, cv,SQLiteDatabase.CONFLICT_IGNORE);
//dbAdapter.getSQLiteDB().insertOrThrow(ButterflyDBAdapter.BUTTERFLY_CATEGORY, null, cv);
}catch(SQLException e) {
e.printStackTrace();
}
}
Log.i(TAG, "Category Values inserted in " + ButterflyDBAdapter.BUTTERFLY_CATEGORY);
}
/**
* Insert the butterfly details such as category id, common name, scientific name and detailed info into the database.
* The number of values in the butterfly_common_names[] determines the number of
* rows to be put in the Butterfly table.
*/
public void insertButterfly(){
for(int i = 0; i<butterfly_common_names.length;i++){
ContentValues cv = new ContentValues();
cv.put(ButterflyDBAdapter.COL_BUTTERFLY_COMMON_NAME, butterfly_common_names[i]);
cv.put(ButterflyDBAdapter.COL_CAT_ID, Integer.parseInt(cat_id[i]));
cv.put(ButterflyDBAdapter.COL_BUTTERFLY_SCIENTIFIC_NAME, butterfly_scientific_names[i]);
try{
dbAdapter.getSQLiteDB().insert(ButterflyDBAdapter.BUTTERFLY, null, cv);
//dbAdapter.getSQLiteDB().insertWithOnConflict(ButterflyDBAdapter.BUTTERFLY_CATEGORY, null, cv,SQLiteDatabase.CONFLICT_IGNORE);
//dbAdapter.getSQLiteDB().insertOrThrow(ButterflyDBAdapter.BUTTERFLY_CATEGORY, null, cv);
}catch(SQLException e) {
e.printStackTrace();
}
}
Log.i(TAG, "Butterfly Values inserted in " + ButterflyDBAdapter.BUTTERFLY);
}
/**
* Close the database and cursor on finish of activity.
*/
@Override
protected void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
dbAdapter.getSQLiteDB().close();
cur.close();
imgIDStorage.closeDB();
detailsStorage.closeDB();
//super.onDestroy();
}
/**
* Close the database and cursor on finish of activity.
*/
@Override
protected void onPause() {
// TOD Auto-generated method stub
super.onPause();
dbAdapter.getSQLiteDB().close();
cur.close();
imgIDStorage.closeDB();
detailsStorage.closeDB();
//super.onPause();
}
}
DDMS的目的如下:
12-09 11:38:53.299: E/Database(1375): android.database.sqlite.SQLiteConstraintException: error code 19: constraint failed
12-09 11:38:53.299: E/Database(1375): at android.database.sqlite.SQLiteStatement.native_execute(Native Method)
12-09 11:38:53.299: E/Database(1375): at android.database.sqlite.SQLiteStatement.execute(SQLiteStatement.java:55)
12-09 11:38:53.299: E/Database(1375): at android.database.sqlite.SQLiteDatabase.insertWithOnConflict(SQLiteDatabase.java:1549)
12-09 11:38:53.299: E/Database(1375): at android.database.sqlite.SQLiteDatabase.insert(SQLiteDatabase.java:1410)
12-09 11:38:53.299: E/Database(1375): at com.myambitionconsultants.butterflyworld.ButterflyWorldActivity.insertButterflyCategory(ButterflyWorldActivity.java:204)
12-09 11:38:53.299: E/Database(1375): at com.myambitionconsultants.butterflyworld.ButterflyWorldActivity.onCreate(ButterflyWorldActivity.java:78)
12-09 11:38:53.299: E/Database(1375): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
12-09 11:38:53.299: E/Database(1375): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2627)
12-09 11:38:53.299: E/Database(1375): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2679)
12-09 11:38:53.299: E/Database(1375): at android.app.ActivityThread.access$2300(ActivityThread.java:125)
12-09 11:38:53.299: E/Database(1375): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2033)
12-09 11:38:53.299: E/Database(1375): at android.os.Handler.dispatchMessage(Handler.java:99)
12-09 11:38:53.299: E/Database(1375): at android.os.Looper.loop(Looper.java:123)
12-09 11:38:53.299: E/Database(1375): at android.app.ActivityThread.main(ActivityThread.java:4627)
12-09 11:38:53.299: E/Database(1375): at java.lang.reflect.Method.invokeNative(Native Method)
12-09 11:38:53.299: E/Database(1375): at java.lang.reflect.Method.invoke(Method.java:521)
12-09 11:38:53.299: E/Database(1375): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
12-09 11:38:53.299: E/Database(1375): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
12-09 11:38:53.299: E/Database(1375): at dalvik.system.NativeStart.main(Native Method)
12-09 11:38:53.369: E/Database(1375): Error inserting CategoryName=Pieridae
12-09 11:38:53.369: E/Database(1375): android.database.sqlite.SQLiteConstraintException: error code 19: constraint failed
12-09 11:38:53.369: E/Database(1375): at android.database.sqlite.SQLiteStatement.native_execute(Native Method)
12-09 11:38:53.369: E/Database(1375): at android.database.sqlite.SQLiteStatement.execute(SQLiteStatement.java:55)
12-09 11:38:53.369: E/Database(1375): at android.database.sqlite.SQLiteDatabase.insertWithOnConflict(SQLiteDatabase.java:1549)
12-09 11:38:53.369: E/Database(1375): at android.database.sqlite.SQLiteDatabase.insert(SQLiteDatabase.java:1410)
12-09 11:38:53.369: E/Database(1375): at com.myambitionconsultants.butterflyworld.ButterflyWorldActivity.insertButterflyCategory(ButterflyWorldActivity.java:204)
12-09 11:38:53.369: E/Database(1375): at com.myambitionconsultants.butterflyworld.ButterflyWorldActivity.onCreate(ButterflyWorldActivity.java:78)
12-09 11:38:53.369: E/Database(1375): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
12-09 11:38:53.369: E/Database(1375): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2627)
12-09 11:38:53.369: E/Database(1375): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2679)
12-09 11:38:53.369: E/Database(1375): at android.app.ActivityThread.access$2300(ActivityThread.java:125)
12-09 11:38:53.369: E/Database(1375): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2033)
12-09 11:38:53.369: E/Database(1375): at android.os.Handler.dispatchMessage(Handler.java:99)
12-09 11:38:53.369: E/Database(1375): at android.os.Looper.loop(Looper.java:123)
12-09 11:38:53.369: E/Database(1375): at android.app.ActivityThread.main(ActivityThread.java:4627)
12-09 11:38:53.369: E/Database(1375): at java.lang.reflect.Method.invokeNative(Native Method)
12-09 11:38:53.369: E/Database(1375): at java.lang.reflect.Method.invoke(Method.java:521)
12-09 11:38:53.369: E/Database(1375): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
12-09 11:38:53.369: E/Database(1375): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
12-09 11:38:53.369: E/Database(1375): at dalvik.system.NativeStart.main(Native Method)
如何处理此类错误?
答案 0 :(得分:1)
查看日志时,错误是“约束失败”,这意味着您尝试将空值插入非空列或具有主键的列。
否则,您尝试将重复值插入到具有主键或唯一键的列中。
然后您可以在插入值之前删除该表。由于值是在应用程序首次启动时插入的,因此从下一次开始,app将尝试插入相同的值。
答案 1 :(得分:0)
您可能应该将用于填充数据库的所有代码,用于将数据从资源传输到数据库的所有方法移动到实际的ButterflyDBAdapter中。在适配器的onCreate()
方法中,您可以检查数据库是否已存在,如果不存在,则使用您的默认数据集填充它。然后,您还可以公开一些用于从数据库插入和检索数据的方法。在ButterflyWorldActivity中,您只需要通过这些方法与数据库进行交互。
答案 2 :(得分:0)
我不明白为什么要在Activity.onCreate()中创建和填充数据库。这只需要在首次启动时完成一次。
在ButterflyDBAdapter中,你有一个扩展SQLiteOpenHelper的类吗?如果是这样,您应该在SQLiteOpenHelper的onCreate()处理程序中创建和填充数据库。你可以发布ButterflyDBAdapter代码吗?