SQLite数据库在调用时无法正常工作

时间:2017-11-07 00:18:48

标签: java android database sqlite navigation-drawer

我将SQLite数据库用于关于不同面条的项目。对于项目,我使用导航抽屉并从数据库中调用数据。不知何故,当我尝试查询数据时,抛出SQLiteException并且没有任何反应。

为什么它不起作用?

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_noodle);
        //set up toolbar as the normal app bar
        Toolbar toolbar = findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);


        SQLiteOpenHelper databaseHelper = new DatabaseHelper(this);
        ListView noodleListPerCategory = findViewById(R.id.selected_noodleList);

        try {
            database = databaseHelper.getReadableDatabase();
            fetch();

            //create the cursor adapter to fill the list view with values from the database
            SimpleCursorAdapter listAdapter = new SimpleCursorAdapter(this, android.R.layout.simple_list_item_1, cursor, new String[]{"NAME"},
                    new int[]{android.R.id.text1}, 0);
            noodleListPerCategory.setAdapter(listAdapter);
        } catch (SQLiteException e) {
            Toast toast = Toast.makeText(this, "Database is  not working!", Toast.LENGTH_SHORT);
            toast.show();
        }

        //show item detail using the listener when an item is clicked
        AdapterView.OnItemClickListener itemClickListener = new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> noodleListPerCategory, View view, int position, long id) {
                //starts DetailActivity
                Intent intent = new Intent(NoodleActivity.this, DetailActivity.class);
                intent.putExtra(DetailActivity.CHOSEN_NOODLE_ITEM, (int) id);
                startActivity(intent);
            }
        };
        //connects the listener to the list view
        noodleListPerCategory.setOnItemClickListener(itemClickListener);
    }

    @Override
         public void onDestroy(){
            super.onDestroy();
            cursor.close();
            database.close();
        }

    public Cursor fetch() {
        cursor = this.database.query("NOODLE", new String[]{"_id", "NAME"}, null, null, null, null, null);
        if (cursor != null) {
            cursor.moveToFirst();
        }
        return cursor;
    }

1 个答案:

答案 0 :(得分:0)

根据此问题和您之前的问题创建了测试。问题主要出在数据库帮助程序类DatabaseHelper;

在关闭数据库的 addNoodle 方法中,这会导致数据库按以下方式关闭: -

11-07 12:59:35.188 2986-2986/? E/AndroidRuntime: FATAL EXCEPTION: main
                                                 Process: mjt.noodle, PID: 2986
                                                 java.lang.RuntimeException: Unable to start activity ComponentInfo{mjt.noodle/mjt.noodle.Noodle}: java.lang.IllegalStateException: attempt to re-open an already-closed object: SQLiteDatabase: /data/data/mjt.noodle/databases/NoodleDB
                                                     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2325)
                                                     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2387)
                                                     at android.app.ActivityThread.access$800(ActivityThread.java:151)
                                                     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1303)
                                                     at android.os.Handler.dispatchMessage(Handler.java:102)
                                                     at android.os.Looper.loop(Looper.java:135)
                                                     at android.app.ActivityThread.main(ActivityThread.java:5254)
                                                     at java.lang.reflect.Method.invoke(Native Method)
                                                     at java.lang.reflect.Method.invoke(Method.java:372)
                                                     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
                                                     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
                                                  Caused by: java.lang.IllegalStateException: attempt to re-open an already-closed object: SQLiteDatabase: /data/data/mjt.noodle/databases/NoodleDB
                                                     at android.database.sqlite.SQLiteClosable.acquireReference(SQLiteClosable.java:55)
                                                     at android.database.sqlite.SQLiteDatabase.endTransaction(SQLiteDatabase.java:520)
                                                     at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:262)
                                                     at android.database.sqlite.SQLiteOpenHelper.getReadableDatabase(SQLiteOpenHelper.java:187)
                                                     at mjt.noodle.Noodle.onCreate(Noodle.java:35)

注意!因为我做了修改以简化测试,所以行号不匹配。 (即显示日志可以让您对问题有所了解)

移除 db.close(); 中的 addNoodle ,然后删除应用<&strong数据或(卸载应用程序)将解决此问题。

理所当然,你也应该替换

SQLiteOpenHelper databaseHelper = new DatabaseHelper(this); Databasehelper databaseHelper = new DatabaseHelper(this);

因为你真的想要一个DatabaseHelper对象而不是一个SQLiteOpenHelper对象。但是,这在现阶段没有引起问题,但后来可能会引起混淆或导致问题。

为了测试这个,我使用了以下内容: -

Noodle.java: -

public class Noodle extends AppCompatActivity {

    private Cursor cursor;
    private SQLiteDatabase database;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_noodle);
        //set up toolbar as the normal app bar
        //Toolbar toolbar = findViewById(R.id.toolbar);
        //setSupportActionBar(toolbar);


        DatabaseHelper databaseHelper = new DatabaseHelper(this);
        ListView noodleListPerCategory = findViewById(R.id.selected_noodleList);

        try {
            database = databaseHelper.getReadableDatabase();
            fetch();

            //create the cursor adapter to fill the list view with values from the database
            SimpleCursorAdapter listAdapter = new SimpleCursorAdapter(this, android.R.layout.simple_list_item_1, cursor, new String[]{"NAME"},
                    new int[]{android.R.id.text1}, 0);
            noodleListPerCategory.setAdapter(listAdapter);
        } catch (SQLiteException e) {
            Toast toast = Toast.makeText(this, "Database is  not working!", Toast.LENGTH_SHORT);
            toast.show();
        }

        //show item detail using the listener when an item is clicked
        AdapterView.OnItemClickListener itemClickListener = new AdapterView.OnItemClickListener() {

            @Override
            public void onItemClick(AdapterView<?> noodleListPerCategory, View view, int position, long id) {
                //starts DetailActivity
                /*
                Intent intent = new Intent(NoodleActivity.this, DetailActivity.class);
                intent.putExtra(DetailActivity.CHOSEN_NOODLE_ITEM, (int) id);
                startActivity(intent);
                */
            }
        };
        //connects the listener to the list view
        noodleListPerCategory.setOnItemClickListener(itemClickListener);
    }

    @Override
    public void onDestroy(){
        super.onDestroy();
        cursor.close();
        database.close();
    }

    public Cursor fetch() {
        cursor = this.database.query("NOODLE", new String[]{"_id", "NAME"}, null, null, null, null, null);
        if (cursor != null) {
            cursor.moveToFirst();
        }
        return cursor;
    }
}

一起

DatabaseHelper.java: -

public class DatabaseHelper extends SQLiteOpenHelper {
    //the name for the database
    private static final String DATABASENAME = "NoodleDB";
    //the initial version of the database
    private static final int DATABASEVERSION = 1;
    private Noodle noodle;
    //SQLiteDatabase db;

    DatabaseHelper(Context context) {
        super(context, DATABASENAME, null, DATABASEVERSION);
        //db = this.getReadableDatabase();

    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        updateDatabase(db, 0, DATABASEVERSION);

    }

    /**
     * this method updates the database if the db helper's version number is higher than the version number on the db.
     *
     * @param db             The SQLite database
     * @param currentVersion The user's version number of the database
     * @param updatedVersion The new version of the database written in the helper's code
     */

    @Override
    public void onUpgrade(SQLiteDatabase db, int currentVersion, int updatedVersion) {
        updateDatabase(db, currentVersion, updatedVersion);
    }

    /**
     * This method is called when you want to set the database back to its previous version
     *
     * @param db             The SQLite database
     * @param currentVersion The user's version number of the database
     * @param updatedVersion The new version of the database written in the helper's code
     */
    public void onDowngrade(SQLiteDatabase db, int currentVersion, int updatedVersion) {

    }

    /**
     * This method is for adding new noodle dish to the database
     */
    private void addNoodle(SQLiteDatabase db, String name, String description, int imageid, String restaurant) {
        ContentValues noodleValues = new ContentValues();
        noodleValues.put("NAME", name);
        noodleValues.put("DESCRIPTION", description);
        noodleValues.put("IMAGEID", imageid);
        noodleValues.put("RESTAURANT", restaurant);
        db.insert("NOODLE", null, noodleValues);
        //db.close();

    }

    private void updateDatabase(SQLiteDatabase db, int currentVersion, int updatedVersion) {
        if(currentVersion >= 1 || currentVersion < 1 ) {
            //execute SQL on the db and create a new NOODLE table
            db.execSQL("CREATE TABLE NOODLE ("
                    + "_id INTEGER PRIMARY KEY AUTOINCREMENT, "
                    + "NAME TEXT, "
                    + "DESCRIPTION TEXT, "
                    + "IMAGEID INTEGER, "
                    + "RESTAURANT TEXT, "
                    + "FAVORITE NUMERIC, "
                    + "CATEGORY TEXT);");
            addNoodle(db,"Spicy Ramen", "Chicken broth, marinated pork, chilli and bean sprouts", 1, "Totemo");
            addNoodle(db,"Tokyo Ramen", "Dashi-based broth, marinated pork and fermented bamboo shoots", 2, "Totemo");
            addNoodle(db,"Vegetarian Ramen", "Mushroom dashi-based broth, tofu, pak choi, miso and corn", 3, "Ramen Manga");
            addNoodle(db,"Miso Ramen", "Miso broth, marinated pork, egg, spring onion and bean sprouts", 4, "Cafe Steigman");
            addNoodle(db,"Tonkatsu Ramen", "Pork bone based broth, grilled pork, spicy garlic with miso", 5, "Blue Light Yokohama");
            addNoodle(db,"Shio Ramen", "Seasalt broth, pork, egg, quail and vegetable", 6, "Ai Ramen");
            addNoodle(db,"Nabeyaki Udon", "Udon noodles in fish broth with chicken, shrimp, egg and leek", 7, "Ki-mama Ramen");
        }
        if(currentVersion <=2) {

        }
    }
}

,虽然相当无关

activity_noodle.xml: -

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="mjt.noodle.Noodle">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!" />
    <ListView
        android:id="@+id/selected_noodleList"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"></ListView>

</LinearLayout>

以上导致: -

enter image description here