zoukankan      html  css  js  c++  java
  • 解决SQLite打开已有路径下的db问题

    最近遇到的需要加载已有路径下(sd card下)db的问题,找了一下资料,以下是解决的方法,仅供参考(转载自eoe):

    SQLiteOpenHelper 是Android框架为我们提供的一个非常好的数据库打开、升级与关闭的工具类。但是这个工具类会自动把db文件创建到“ /data/data/com.*.*(package name)/” 目录下,这么做可能是与Android文件系统的设计思路有关。

    但 是在实战过程中,我们可能有各种原因需要自定义db文件路径(例如db文件较大放到sd卡更安全等等),相信很多人都遇到了这个需求,网上也有很多解决方 法,这些方法大多是抛弃Android框架为我们提供的SQLiteOpenHelper类,自己重头写一个DbHelper类完成自定义路径的数据库打 开关闭等。这么做虽然可以解决问题,但并不是一个最好的方法,因为自己写的DbHelper可靠性和功能自然难和google巨匠相。

    本文提出一种方法,通过继承和添加代码,并复用SQLiteOpenHelper的代码,来解决自定义db路径的问题。

    首 先我们来分析一下SQLiteOpenHelper的源代码。getReadableDatabase()和getWritableDatabase() 在内部都是调用getDatabaseLocked()。getDatabaseLocked()的源代码很容易理解,分析得知:

    • 如果以只读方式打开,是通过mContext.getDatabasePath(mName)来获取db文件的路径并使用SQLiteDatabase.openDatabase()直接打开数据库;
    • 如 果以读写方式打开,是通过mContext.openOrCreateDatabase(mName, mEnableWriteAheadLogging ? Context.MODE_ENABLE_WRITE_AHEAD_LOGGING : 0, mFactory, mErrorHandler)打开或创建数据库。

    所以我们需要改变mContext的行为。Android框架提供了一个ContextWrapper类,是Context的一个代理,可以通过继承的方式拉改变Context的行为,所以我们继承ContextWrapper,代码如下:

    class CustomPathDatabaseContext extends ContextWrapper{
        private String mDirPath;

      public CustomPathDatabaseContext(Context base, String dirPath) {

        super(base);

        this.mDirPath = dirPath;

      }
                   

      @Override

      public File getDatabasePath(String name) {

        File result = new File(mDirPath + File.separator + name);

        if (!result.getParentFile().exists()){

          result.getParentFile().mkdirs();

        }

        return result;

        }

        

      @Override

      public SQLiteDatabase openOrCreateDatabase(String name, int mode ,CursorFactory factory){

        return SQLiteDatabase.openOrCreateDatabase(getDatabasePath(name), factory);

      }

      

      @Override

      public SQLiteDatabase openOrCreateDatabase(String name, int mode, CursorFactory factory, DatabaseErrorHandler errorHandler){

        return SQLiteDatabase.openOrCreateDatabase(getDatabasePath(name).getAbsolutePath(), factory, errorHandler);

      }
      }

    上述代码很简单了,就不用多说明了吧,然后我们在继承SQLiteOpenHelper时这么写就可以了:

    class YourDbHelper extends SQLiteOpenHelper{

            public YourDbHelper(Context context, String name, CursorFactory factory,
                            int version) {
                    super(new CustomPathDatabaseContext(context, getDirPath()), name, factory, version);
            }

            /**
             * 获取db文件在sd卡的路径
             * @return
             */
            private static String getDirPath(){
                    //TODO 这里返回存放db的文件夹的绝对路径
                    return "";
            }
            
            @Override
            public void onCreate(SQLiteDatabase db) {
            }

            @Override
            public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
            }
            
      }

    如此一来,我们既可以自定义db文件路径,又可以复用SQLiteOpenHelper十分好用的功能了~

     

    另外需要注意的是,有些应 用可能是有一个已建好表的db文件放在assets中,应用运行时先判断db文件是否存在,如果不存在则从assets中复制到自定义路径。这种情况通常 都是在PC端使用SQLiteSpy诸如此类的工具写sql建表,使用这种方法的小伙伴们别忘了在建表时执行  PRAGMA schema_version = 1   这句sql(当然了版本号取决于您的需求) , 否则SQLiteOpenHelper还是会触发onCreate的~看了SQLiteOpenHelper什么时候触发onCreate的源码就明白怎么回事了~

     

  • 相关阅读:
    Linux内核RPC请求过程
    二分图
    Java实现 蓝桥杯 算法提高 合并石子
    Java实现 蓝桥杯 算法提高 合并石子
    Java实现 蓝桥杯 算法提高 摩尔斯电码
    Java实现 蓝桥杯 算法提高 摩尔斯电码
    Java实现 蓝桥杯 算法提高 文本加密
    Java实现 蓝桥杯 算法提高 文本加密
    Java蓝桥杯 算法提高 九宫格
    Java蓝桥杯 算法提高 九宫格
  • 原文地址:https://www.cnblogs.com/zzcc/p/4107994.html
Copyright © 2011-2022 走看看