DbUtils應用在Android6.0中爲何會崩潰

序言

最近研究了一個手機開門的功能,在Android4.X/5.X測試都經過了,後來在Android6.0上測試崩潰了,適配出現了問題,究竟是什麼緣由呢?java

分析

Logcat裏面的報錯信息是這樣的
java.lang.NullPointerException: Attempt to invoke virtual method 'int android.database.sqlite.SQLiteDatabase.getVersion()' on a null object reference
初始化數據庫出現了問題,獲取不到數據庫的版本號,剛開始覺得是開門的jar包不兼容,致使建立數據庫失敗,可是通過查找資料和反覆調試,發現問題出在DbUtils上,究竟是什麼問題呢?android

首先了解一下DbUtils的框架結構,整體來看分爲7個部分:
一、create instance(建立實例)
二、operations(操做部分)
三、config(配置)
四、private operations with out transaction(無業務的操做)
五、tools(工具)
六、exec sql(sql執行)
七、temp cache(臨時緩存)sql

其中在建立數據庫的時候提供了5種構造方法數據庫

(1)經過傳入上下文建立DB,這種狀況下使用的是系統默認的配置緩存

dbName = xUtils.db, dbVersion = 1;    
  public static DbUtils create(Context context) {
        DaoConfig config = new DaoConfig(context);
        return getInstance(config);
    }

(2)經過傳入上下文和dbName,根據用戶指定的dbName生成數據庫服務器

public static DbUtils create(Context context, String dbName) {
    DaoConfig config = new DaoConfig(context);
    config.setDbName(dbName);
    return getInstance(config);
}

(3) 經過傳入上下文 、dbDir、dbName,根據用戶指定的dbName在dbDir位置生成數據庫
public static DbUtils create(Context context, String dbDir, String dbName) {框架

DaoConfig config = new DaoConfig(context);
    config.setDbDir(dbDir);
    config.setDbName(dbName);
    return getInstance(config);
}

(4) 經過傳入上下文 、dbName,dbVersion、dbUpgradeListener根據用戶指定的dbName生成dbVersion版 的數據庫
public static DbUtils create(Context context, String dbName, int dbVersion, DbUpgradeListener dbUpgradeListener) {工具

DaoConfig config = new DaoConfig(context);
    config.setDbName(dbName);
    config.setDbVersion(dbVersion);
    config.setDbUpgradeListener(dbUpgradeListener);
    return getInstance(config);
}

(5) 經過傳入上下文 、dbName,dbVersion、dbUpgradeListener,根據用戶指定的dbName生成dbVersion的數據庫 ,指定監聽器
public static DbUtils create(Context context, String dbDir, String dbName, int dbVersion, DbUpgradeListener dbUpgradeListener) {測試

DaoConfig config = new DaoConfig(context);
    config.setDbDir(dbDir);
    config.setDbName(dbName);
    config.setDbVersion(dbVersion);
    config.setDbUpgradeListener(dbUpgradeListener);
    return getInstance(config);
}

5種方法怎麼選擇呢?咱們看下用於配置數據庫的5個屬性優化

private Context context; //上下文
private String dbDir;//數據庫存儲路徑
private String dbName = 「xUtils.db」; // 數據庫名稱 
private int dbVersion = 1; //版本號
private DbUpgradeListener dbUpgradeListener;//監聽器

爲了方便咱們後期查找,通常會選擇第三種構造方法,指定上下文,指定數據庫的名稱,指定數據庫存儲路徑,大多數狀況這是沒有問題的,可是Android6.0和之前的版本相比,對存儲路徑作了修改,因此根據Android4.X/5.X給出的指定存儲路徑不適用於6.0版本,建立數據庫失敗,就出現的文章開頭的錯誤,獲取數據庫版本號失敗。

找到了問題所在,那麼解決起來就相對簡單了,只要選擇第一種構造方法,指定上下文,其餘屬性根據系統自動適配就能夠了。

其實還有一種相對簡單的解決方法,做爲手機端,大部分數據都是從服務器獲取的,在數據量不是很大的狀況下,並不須要去生成數據庫,能夠在獲取數據後,只作一個簡單的緩存,保存到集合中,如List,map等,大多數頁面如今都是這樣實現的。

其實出現這種狀況的不光是Android6.0,因爲市場上Android手機品牌型號較多,不一樣品牌,不一樣型號的手機,爲了實現某些個性化功能,或者出於優化內存等方面的考慮,常常會篡改手機的存儲路徑,以前在作其餘功能,好比獲取手機本地的視頻文件,圖片文件等,都遇到了這樣的適配問題,下次有時間再分享。

總結

遇到不熟悉的錯誤信息,能夠把錯誤信息複製出來,經過百度大致瞭解一下,出現這種錯誤都有些什麼緣由,把握好大方向,而後從熟悉的內容入手,分析可能出現錯誤代碼的內部機制,找出可能會產生相關錯誤的點,逐步排除改進,最後解決問題。

相關文章
相關標籤/搜索