1. 程式人生 > >【Android】GreenDao操作外部DB資料庫檔案

【Android】GreenDao操作外部DB資料庫檔案

1.背景

所謂外部資料庫檔案此處指的就是一個在外部單獨建立的db檔案,假設有這麼一個場景,我們專案中有一些本地資料,不需要介面去獲取的(不需要進行網路操作),寫死的資料,比如全國各個省各個市的一些基本資訊,每個市的資訊可以作為表裡的一條記錄存放,在專案中使用,此時如何我們已經有了包含這些資訊的db檔案,我們就可以通過greendao來操作這個db檔案,更具方便進行開發工作,當然這只是個模擬情況,至於合不合理,有沒有更好的方式,此處不過多討論,重點講這麼一種方式,這種方式可以用於一些不經常變化的資料。

2.專案配置

  • 首先看一下專案結構:

這裡寫圖片描述

res/raw目錄存放的就是外部的db檔案的壓縮檔案,我們可以開啟看一下資料庫結構,db檔案包含兩張表,student和teacher裡面簡單的插入了幾條測試資料:

這裡寫圖片描述
這裡寫圖片描述

  • 引入greendao庫檔案或者引用庫工程:

這裡寫圖片描述

2.程式碼實現

實現之前先說一下具體的思路,程式執行,首先把raw目錄下的db檔案拷貝到資料庫儲存的預設目錄,然後通過greendao的api對這個檔案進行操作即可;

  • 我們需要獲取應用db儲存的路徑,通過如下方式:
private void getAppInfo()
    {
        // 獲取packageManager的例項
        PackageManager packageManager = getPackageManager();
        // getPackageName()是你當前類的包名,0代表是獲取版本資訊
try { packInfo = packageManager.getPackageInfo(getPackageName(), 0); } catch (NameNotFoundException e) { e.printStackTrace(); } }
  • 通過以上方式即可獲取到資料庫的路徑:
    這裡寫圖片描述

  • 拷貝操作:

public static boolean copyRawDBToApkDb(Context context, int copyRawDbResId, String apkDbPath, String dbName,boolean
refresh) throws IOException { boolean b = false; File f = new File(apkDbPath); if (!f.exists()) { f.mkdirs(); } File dbFile = new File(apkDbPath + dbName); b = isDbFileExists(dbFile,refresh); if (!b) { InputStream is = context.getResources().openRawResource(copyRawDbResId); ZipInputStream zis = new ZipInputStream(new BufferedInputStream(is)); ZipEntry entry; while ((entry = zis.getNextEntry()) != null) { int size; byte[] buffer = new byte[1024 * 2]; OutputStream fos = new FileOutputStream(apkDbPath + entry.getName()); BufferedOutputStream bos = new BufferedOutputStream(fos, buffer.length); while ((size = zis.read(buffer, 0, buffer.length)) != -1) { bos.write(buffer, 0, size); } bos.flush(); bos.close(); } zis.close(); is.close(); } return !b; }

此處是拷貝操作的關鍵程式碼,需要我們傳入raw資源ID,資料庫的拷貝路徑,資料庫檔名,是否覆蓋已經存在的db檔案,@return 拷貝是否成功,關於refresh引數,我們一般希望只拷貝一次,當我們在某些情況下更新了這個db檔案的話就可以設定為true進行覆蓋操作;

  • 使用greenDao java工程,生成外部db檔案所對應表的實體類Dao類等程式碼:

這裡寫圖片描述

上圖中的DBController類是我封裝的資料庫操作類,更方便我們去進行操作,DBController的關鍵程式碼如下:

/**
 * 外部資料庫控制類
 */
public class DBController
{
    private static DaoMaster daoMasterEcmc;

    private static DaoMaster daoMasterSchool;

    // 預設DB
    private static DaoSession daoSessionDefault;

    // 拷貝的db
    private static DaoSession daoSchoolSession;

    /**
     * 預設資料庫名稱:localdata
     */
    public static final String DATABASE_NAME = "localdata.db";

    /**
     * 拷貝資料庫名稱:school
     */
    public static final String DATABASE_SCHOOL_NAME = "school.db";

    private static DaoMaster obtainMaster(Context context, String dbName)
    {
        return new DaoMaster(new DaoMaster.DevOpenHelper(context, dbName, null).getWritableDatabase());
    }

    private static DaoMaster getDaoMaster(Context context, String dbName)
    {
        if (dbName == null)
            return null;
        if (daoMasterEcmc == null)
        {
            daoMasterEcmc = obtainMaster(context, dbName);
        }
        return daoMasterEcmc;
    }

    private static DaoMaster getSchoolDaoMaster(Context context, String dbName)
    {
        if (dbName == null)
            return null;
        if (daoMasterSchool == null)
        {
            daoMasterSchool = obtainMaster(context, dbName);
        }
        return daoMasterSchool;
    }

    /**
     * 取得DaoSession
     *
     * @return
     */
    public static DaoSession getDaoSession(String dbName)
    {

        if (daoSchoolSession == null)
        {
            daoSchoolSession = getSchoolDaoMaster(MainApplication.getIns(), dbName).newSession();
        }
        return daoSchoolSession;
    }

    /**
     * 預設操作localdata資料庫
     */
    public static DaoSession getDaoSession()
    {

        if (daoSessionDefault == null)
        {
            daoSessionDefault = getDaoMaster(MainApplication.getIns(), DATABASE_NAME).newSession();
        }
        return daoSessionDefault;
    }
}
  • 可能我們還需要預設的greendao資料庫進行其他的操作,至於預設的操作此處不再詳細介紹,不瞭解的可以看greendao基本使用,此處我們演示的外部DB檔案命名為school.db,預設的greenDao資料庫命名為history.db,下面我們在MainActivity進行測試操作:
public class MainActivity extends Activity
{
    private StringBuilder builder;

    @Override
    protected void onCreate(Bundle savedInstanceState)
    {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //建立預設的資料,並插入一條資料
        HistoryDao historyDao = DBLocalController.getDaoSession().getHistoryDao();
        History entity = new History();
        entity.setName("科羅拉多");
        entity.setImageUrl("http://www.baidu.com");
        historyDao.insert(entity);
        //拷貝外部DB檔案到指定目錄
        copyRawDB();
        //通過greendao查詢外部db檔案資料
        selDBData();
    }

    private void selDBData()
    {
        StudentDao student = DBController.getDaoSession(DBController.DATABASE_SCHOOL_NAME).getStudentDao();
        List<Student> students = student.queryBuilder().list();
        builder = new StringBuilder();
        for (int i = 0; i < students.size(); i++)
        {
            builder.append(students.get(i).getName() + "---");
        }
        Toast.makeText(MainActivity.this, builder.toString(), Toast.LENGTH_SHORT).show();
    }

    private void copyRawDB()
    {
        try
        {
            // 拷貝res/raw/xxxxdb.zip 到
            // /data/data/com.xinhang.mobileclient/databases/ 目錄下面
            boolean isSuccess = DBUtils.copyRawDBToApkDb(MainActivity.this, R.raw.schooldb, DBUtils.APK_DB_PATH, DBUtils.ECMC_DB_NAME, false);
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
    }

}

執行結果:

這裡寫圖片描述

可以看到我們的外部db檔案已經拷貝到資料庫預設路徑下,還有我們的預設資料庫也建立成功;區分兩個資料庫的方式是通過DBLocalController.getDaoSession(name)方法,想操作哪個資料庫傳入對應的資料庫名稱即可,gif操作圖如下;

這裡寫圖片描述