解決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的源碼就明白怎么回事了~

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM