使用SQLiteOpenHelper管理SD卡中的数据库

本人在网上找了好多大牛的资料,研究了几天终于调试出来了。以下是笔记;

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,复写它的openOrcreatDatabase()方法,然后实例化SQLiteOpenHelper时,传我们复写的Context进去就可以了。

代码如下:

 1 package com.slc.qhfpsj.DAO;
 2 
 3 import android.content.Context;
 4 import android.content.ContextWrapper;
 5 import android.database.DatabaseErrorHandler;
 6 import android.database.sqlite.SQLiteDatabase;
 7 import android.util.Log;
 8 
 9 import java.io.File;
10 
11 /**
12  * Created by Administrator on 2015/11/22.
13  * Coder:Mengjinluohua
14  * version:1.0
15  */
16 public class DatabaseContext extends ContextWrapper {
17     public DatabaseContext(Context base) {
18         super(base);
19     }
20 
21     /**
22      * 获得数据库路径,如果不存在,则创建对象对象
23      *
24      * @param    name
25      *
26      */
27     @Override
28     public File getDatabasePath(String name) {
29 //        return super.getDatabasePath(name);
30         //判断是否存在sd卡
31         boolean sdExist = android.os.Environment.MEDIA_MOUNTED.equals(android.os.Environment.getExternalStorageState());
32         if (!sdExist) {//如果不存在,
33             Log.e("SD卡管理:", "SD卡不存在,请加载SD卡");
34             return null;
35         } else {//如果存在
36             //获取sd卡路径
37 //            String dbDir= FileUtils.getFlashBPath();
38             String dbDir = android.os.Environment.getExternalStorageDirectory().getAbsolutePath();//sd卡路径
39             dbDir += "/DB";//数据库所在目录  在这里修改SD卡下文件的保存路径
40 //            String dbPath = dbDir + "/" + name;//数据库路径
41             File dbfile = getFilePath(dbDir, name);
42             return dbfile;
43 
44         }
45     }
46 
47 
48     private File getFilePath(String dbDir, String name) {
49         File file = null;
50         makeRootDirectory(dbDir);
51         try {
52             file = new File(dbDir+ "/" + name);
53         } catch (Exception e) {
54             // TODO Auto-generated catch block
55             e.printStackTrace();
56         }
57         return file;
58 
59 
60     }
61 
62     private void makeRootDirectory(String dbPath) {
63         File file = null;
64         try {
65             file = new File(dbPath);
66             if (!file.exists()) {
67                 file.mkdir();
68             }
69         } catch (Exception e) {
70 
71         }
72     }
73 
74 
75 
76     @Override
77     public SQLiteDatabase openOrCreateDatabase(String name, int mode, SQLiteDatabase.CursorFactory factory) {
78         SQLiteDatabase result = SQLiteDatabase.openOrCreateDatabase(getDatabasePath(name), null);
79         return result;
80     }
81     @Override
82     public SQLiteDatabase openOrCreateDatabase(String name, int mode, SQLiteDatabase.CursorFactory factory,
83                                                DatabaseErrorHandler errorHandler) {
84         SQLiteDatabase result = SQLiteDatabase.openOrCreateDatabase(getDatabasePath(name), null);
85         return result;
86     }
87 
88 }

然后我们在继承SQLiteOpenHelper时这么写就可以了:

 1 package com.slc.qhfpsj.DAO;
 2 
 3 import android.content.Context;
 4 import android.database.SQLException;
 5 import android.database.sqlite.SQLiteDatabase;
 6 import android.database.sqlite.SQLiteOpenHelper;
 7 import android.util.Log;
 8 
 9 /**
10  * Created by Administrator on 2015/11/23.
11  * Coder:Mengjinluohua
12  * version:1.0
13  */
14 public class SdCardDBHelper extends SQLiteOpenHelper {
15 
16     public static final String TAG = "SdCardDBHelper";
17     /**
18      * 数据库名称
19      **/
20     public static String DATABASE_NAME = "sddb.db";
21 
22     /**
23      * 数据库版本
24      **/
25     public static int DATABASE_VERSION = 2;
26 
27     /**
28      * 构造函数
29      *
30      * @param    context 上下文环境
31      **/
32     public SdCardDBHelper(Context context) {
33         super(context, DATABASE_NAME, null, DATABASE_VERSION);
34     }
35 
36     @Override
37     public void onCreate(SQLiteDatabase db) {
38         Log.e(TAG, "开始创建数据库表");
39         try{
40             //创建用户表(user)
41             db.execSQL("create table PovertyFamilyMumberListInfoTab (_id integer primary key autoincrement,name varchar(20)," +
42                     "ID varchar(30),sex varchar(10),relationship varchar(20),people varchar(10),educationDegree varchar(30),studentCondition varchar(30)," +
43                     "healthCondition varchar(30),workAbility varchar(30),workCondition varchar(30),workTime varchar(30),isJoinVillageMedical integer(10)," +
44                     "isJoinCityOrTownMedical integer(10))");
45             Log.e(TAG, "创建离线所需数据库表成功");
46 
47         }
48         catch(SQLException se){
49             se.printStackTrace();
50             Log.e(TAG, "创建离线所需数据库表失败");
51 
52 
53         }
54 
55     }
56 
57     @Override
58     public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
59 
60     }
61 }

这样使用:建立一个 DAO类 操作数据库

 1 public class Jbqk_listinfoDAO {
 2 
 3     private final SdCardDBHelper sdCardDBHelper;
 4 
 5     public Jbqk_listinfoDAO(Context context) {
 6         DatabaseContext databaseContext = new DatabaseContext(context);
 7         sdCardDBHelper = new SdCardDBHelper(databaseContext);
 8     }
 9  
10     public boolean add(String name, String sex, String ID, String relationship, String people, String educationDegree, String studentCondition,
11                        String healthCondition,
12                        String workAbility, String workCondition, String workTime, String isJoinVillageMedical, String isJoinCityOrTownMedical) {
13 
14         SQLiteDatabase db = sdCardDBHelper.getWritableDatabase();
15         ContentValues contentValues = new ContentValues();
16         contentValues.put("ID", ID);
17         contentValues.put("name", name);
18         contentValues.put("sex", sex);
19         contentValues.put("relationship", relationship);
20         contentValues.put("people", people);
21         contentValues.put("educationDegree", educationDegree);
22         contentValues.put("studentCondition", studentCondition);
23         contentValues.put("healthCondition", healthCondition);
24         contentValues.put("workAbility", workAbility);
25         contentValues.put("workCondition", workCondition);
26         contentValues.put("workTime", workTime);
27         contentValues.put("isJoinVillageMedical", isJoinVillageMedical);
28         contentValues.put("isJoinCityOrTownMedical", isJoinCityOrTownMedical);
29 
30         long rowid = db.insert("PovertyFamilyMumberListInfoTab", null, contentValues);
31 
32         if (rowid == -1) {
33             return false;
34         } else {
35             return true;
36         }
37 
38 
39     }
40 }

 测试代码:

 1  public void testAdd() {
 2         DatabaseContext databaseContext = new DatabaseContext(mcontext);
 3         Jbqk_listinfoDAO Dao = new Jbqk_listinfoDAO(databaseContext);
 4 
 5 
 6         for (int i = 0; i < Cheeses.name.length; i++) {
 7             String name = Cheeses.name[i];
 8             String ID = Cheeses.ID[i];
 9             String sex = Cheeses.sex[i];
10             String relationship = Cheeses.relationship[i];
11             String people = Cheeses.people[i];
12             String educationDegree = Cheeses.educationDegree[i];
13             String studentCondition = Cheeses.studentCondition[i];
14             String healthCondition = Cheeses.healthCondition[i];
15             String workAbility = Cheeses.workAbility[i];
16             String workCondition = Cheeses.workCondition[i];
17             String workTime = Cheeses.workTime[i];
18             String isJoinVillageMedical = Cheeses.isJoinVillageMedical[i];
19             String isJoinCityOrTownMedical = Cheeses.isJoinCityOrTownMedical[i];
20 
21             boolean add = Dao.add(name, sex, ID, relationship, people, educationDegree, studentCondition, healthCondition,
22                     workAbility, workCondition, workTime, isJoinVillageMedical, isJoinCityOrTownMedical);
23         }
24     }
25 
26   
27  

 

 

 

 

 

 

posted @ 2015-11-24 11:10  梦尽落花  阅读(957)  评论(0编辑  收藏  举报