如何在android中正确处理数据库的方法

时间:2011-12-09 13:52:51

标签: android database

我对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)

如何处理此类错误?

3 个答案:

答案 0 :(得分:1)

查看日志时,错误是“约束失败”,这意味着您尝试将空值插入非空列或具有主键的列。

否则,您尝试将重复值插入到具有主键或唯一键的列中。

然后您可以在插入值之前删除该表。由于值是在应用程序首次启动时插入的,因此从下一次开始,app将尝试插入相同的值。

答案 1 :(得分:0)

您可能应该将用于填充数据库的所有代码,用于将数据从资源传输到数据库的所有方法移动到实际的ButterflyDBAdapter中。在适配器的onCreate()方法中,您可以检查数据库是否已存在,如果不存在,则使用您的默认数据集填充它。然后,您还可以公开一些用于从数据库插入和检索数据的方法。在ButterflyWorldActivity中,您只需要通过这些方法与数据库进行交互。

答案 2 :(得分:0)

我不明白为什么要在Activity.onCreate()中创建和填充数据库。这只需要在首次启动时完成一次。

在ButterflyDBAdapter中,你有一个扩展SQLiteOpenHelper的类吗?如果是这样,您应该在SQLiteOpenHelper的onCreate()处理程序中创建和填充数据库。你可以发布ButterflyDBAdapter代码吗?