Android SQLiteOpenHelper.close()和SQLiteDatabase.close()之间有什么区别?

Android SQLiteOpenHelper.close()和SQLiteDatabase.close()之间有什么区别?,android,android-sqlite,Android,Android Sqlite,调用SQLiteOpenHelper.close()时会发生什么,调用SQLiteDatabase.close()时会发生什么 对于我的android应用程序,我总是创建Application类的子类,该类有一个MySQLiteOpenHelper实例,它是SQLiteOpenHelper的子类,将由服务、活动和广播接收器等所有应用程序组件共享 在MySQLiteOpenHelper中,我有一个SQLiteDatabase的实例。我在Application.onCreate()方法中创建了MyS

调用
SQLiteOpenHelper.close()
时会发生什么,调用
SQLiteDatabase.close()时会发生什么

对于我的android应用程序,我总是创建
Application
类的子类,该类有一个
MySQLiteOpenHelper
实例,它是
SQLiteOpenHelper
的子类,将由服务、活动和广播接收器等所有应用程序组件共享

MySQLiteOpenHelper
中,我有一个
SQLiteDatabase
的实例。我在Application.onCreate()方法中创建了
MySQLiteOpenHelper
的实例,并且从未对任何
SQLiteOpenHelper
SQLiteDatabase
实例调用
close()
。虽然我对
query()
返回的每个游标对象和每个
SQLiteStatement
显式调用close(),但我使用它来插入、更新或删除数据

到现在为止,它工作得很好,没有任何问题。但最近我收到了用户的留言。引发的异常是
SQLiteDatabaseLockedException
。我读过文件,上面写着

如果数据库引擎无法获取执行其工作所需的数据库锁,则引发

我不明白,当我只使用一个数据库实例,并且文档中说所有数据库调用都是由系统序列化的时候,他们在获取数据库锁方面怎么会有问题。此外,我不会使用beginTransaction()或任何其他相关方法启动或结束任何数据库事务

经过一些搜索之后,我认为应该在数据库连接上调用
close()

我的问题是:

  • 我在这里使用的方法是否正确(我不需要在其他应用程序或第三方应用程序之间共享数据,因此不使用ContentProviders)

  • 我应该什么时候关闭数据库连接

  • 另外,我应该在
    MySQLiteOpenHelper
    SQLiteDatabase
    上调用close吗

  • MySQLiteOpenHelper.java的代码:

    MyApplication.java的代码

    在任何应用程序组件中使用代码:


    SQLiteOpenHeloper::close()
    SQLiteDatabase::close()
    之间没有区别

    SQLiteOpenHeloper::close()
    只是
    SQLiteDatabase::close()
    的包装

    但根据经验,要么让
    SQLiteOpenHelper
    管理您的连接,要么不使用它自己管理它

    请看这篇博文。我将
    SQLiteOpenHelper
    与我自己的预加载数据库一起使用,但是可以很好地使用
    SQLiteOpenHelper
    ,让它管理连接

    更新 这是
    SQLiteOpenHelper::close()
    的源代码:


    您可以演示如何创建和访问MySQLiteOpenHelper实例吗?@boulder请参考编辑后的问题获取代码。为什么不在初始化MySQLiteOpenHelper实例之前将附带的数据库文件复制到假定的位置?SQLiteOpenHelper和SQLiteDatabase close()之间的区别在于SQLiteOpenHelper只关闭SQLiteDatabase的内部实例。让我们
    SQLiteOpenHeloper::close()和SQLiteDatabase::close()之间没有区别。您对此有任何参考资料,以及相关文档的链接吗?
    
    public class MySQLiteOpenHelper extends SQLiteOpenHelper {
    
            public static String TAG = Common.MAIN_TAG + "MySQLiteOpenHelper";
    
            public static int DATABASE_VERSION = 19;
    
            private static String DB_PATH = null;
            public static final String DB_NAME = "data.sqlite";
            private SQLiteDatabase db;
    
            private final Context context;
    
            /**
             * Constructor Takes and keeps a reference of the passed context in order to
             * access to the application assets and resources.
             * 
             * @param context
             */
            public MySQLiteOpenHelper(Context context) {
                super(context, DB_NAME, null, DATABASE_VERSION);
                DB_PATH = "/data/data/" + context.getPackageName().replace("/", "")
                        + "/databases/";
                this.context = context;
            }
    
            /**
             * Creates a empty database on the system and rewrites it with your own
             * database.
             * */
            public void createDataBase() throws IOException {
    
                // Log.v(TAG, "Create database checkpoint - 1");
                boolean dbExist = checkDataBase();
                // Log.v(TAG, "Create database checkpoint - 2");
                if (dbExist) {
                    // Log.v(TAG,
                    // "Create database checkpoint - 3 - database already exists");
                } else {
                    // Log.v(TAG,
                    // "Create database checkpoint - 3 - database needs to be copied");
                    // Log.v(TAG, "Create database checkpoint - 4");
                    try {
                        copyDataBase();
                        checkDataBase();
                        // Log.v(TAG,
                        // "Create database checkpoint - 5 - database cpoied");
                    } catch (IOException e) {
                        e.printStackTrace();
                        throw new Error("Error copying database");
                    }
                }
            }
    
            void copyDatabaseToSdCard() throws IOException {
                if (Log.isInDebugMode()) {
                    InputStream input = null;
                    FileOutputStream output = null;
    
                    int c;
                    byte[] tmp;
                    try {
                        File databaseFile = new File(
                                Environment.getExternalStorageDirectory(),
                                Common.MAIN_TAG + "sqlite");
                        if (databaseFile.exists()) {
                            databaseFile.delete();
                        }
                        databaseFile.createNewFile();
                        output = new FileOutputStream(databaseFile);
                        int i = 0;
    
                        input = new FileInputStream(new File(DB_PATH + DB_NAME));
                        tmp = new byte[1024];
                        while ((c = input.read(tmp)) != -1) {
                            i++;
                            output.write(tmp, 0, c);
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    } finally {
                        if (input != null) {
                            input.close();
                        }
                        if (output != null) {
                            output.close();
                            output.close();
                        }
                    }
                }
            }
    
            /**
             * Check if the database already exist to avoid re-copying the file each
             * time you open the application.
             * 
             * @return true if it exists, false if it doesn't
             */
            private boolean checkDataBase() {
                // Log.v(TAG, "Check database checkpoint - 1");
                SQLiteDatabase checkDB = null;
                try {
                    // checkDB = getWritableDatabase();
                    String myPath = DB_PATH + DB_NAME;
                    checkDB = SQLiteDatabase.openDatabase(myPath, null,
                            SQLiteDatabase.OPEN_READWRITE);
                    // Log.v(TAG,
                    // "Check database checkpoint - 2 - got database file on device");
                    checkDB.close();
                    getWritableDatabase().close();
                    // Log.v(TAG, "Check database checkpoint - 3");
                } catch (Exception e) {
                    // Log.v(TAG,
                    // "Check database checkpoint - 4 - database does not exists on device");
                    // database does't exist yet.
                    if (checkDB != null)
                        checkDB.close();
                    // Log.v(TAG, "Check database checkpoint - 5");
                }
    
                return checkDB != null ? true : false;
            }
    
            /**
             * Copies your database FROM your local raw-folder to the just created empty
             * database in the system folder, FROM where it can be accessed and handled.
             * This is done by transfering bytestream.
             * */
            private void copyDataBase() throws IOException {
                // Log.v(TAG, "Copy database checkpoint - 1");
                InputStream input = null;
                FileOutputStream output = null;
                SQLiteDatabase myDB = null;
    
                myDB = context.openOrCreateDatabase(DB_NAME, 0, null);
                if (myDB != null) {
                    myDB.close();
                }
    
                int c;
                byte[] tmp;
                try {
                    File databaseFile = new File(DB_PATH, DB_NAME);
                    databaseFile.mkdirs();
                    databaseFile.createNewFile();
                    output = new FileOutputStream(DB_PATH + DB_NAME);
                    int i = 0;
    
                    input = context.getResources().openRawResource(R.raw.hcgtabletdb);
                    tmp = new byte[1024];
                    while ((c = input.read(tmp)) != -1) {
                        i++;
                        output.write(tmp, 0, c);
                    }
                    // Log.v(TAG, "Finished copying database");
                } catch (Exception e) {
                    e.printStackTrace();
                    // Log.e(TAG, "Error in copying database" + DB_NAME);
                } finally {
                    if (input != null) {
                        input.close();
                    }
                    if (output != null) {
                        output.close();
                        output.close();
                    }
                }
            }
    
            @Override
            public void onCreate(SQLiteDatabase db) {
                createDataBase();
            }
    
            @Override
            public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
            }
    
            public int getIdFor(String name) {
                String query = "SELECT * FROM bloodpressure WHERE userid=" + userId
                    + " ORDER BY createdon, timecreatedon";
                Cursor cur = db.rawQuery(query, new String[] {});
                int id = cur.getInt(0);
                cur.close();
                return cur;
            }
    }
    
    public class MyApplication extends Application {
    
        private static MyApplication singleton;
        private MySQLiteOpenHelper dbHelper;
    
        public static MyApplication getInstance() {
            return singleton;
        }
    
        @Override
        public void onCreate() {
            super.onCreate();
            singleton = this;
            dbHelper = new MySQLiteOpenHelper(getApplicationContext());
            // Some code
        }
    
        public MySQLiteOpenHelper getDatabaseHelper() {
            return dbHelper;
        }
    
    }
    
    int id = MyApplication.getInstance().getDatabaseHelper().getIdFor("ashish");
    
    /**
     * Close any open database object.
     */
    public synchronized void close() {
        if (mIsInitializing) throw new IllegalStateException("Closed during initialization");
    
        if (mDatabase != null && mDatabase.isOpen()) {
            mDatabase.close();
            mDatabase = null;
        }
    }