博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
使用SQLiteOpenHelper管理SD卡中的数据库
阅读量:4971 次
发布时间:2019-06-12

本文共 8621 字,大约阅读时间需要 28 分钟。

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

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:Mengjinluohua14  * version:1.015  */16 public class DatabaseContext extends ContextWrapper {17     public DatabaseContext(Context base) {18         super(base);19     }20 21     /**22      * 获得数据库路径,如果不存在,则创建对象对象23      *24      * @param    name25      *26      */27     @Override28     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 block55 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 @Override77 public SQLiteDatabase openOrCreateDatabase(String name, int mode, SQLiteDatabase.CursorFactory factory) {78 SQLiteDatabase result = SQLiteDatabase.openOrCreateDatabase(getDatabasePath(name), null);79 return result;80 }81 @Override82 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:Mengjinluohua12  * version:1.013  */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     @Override37     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     @Override58     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

 

 

 

 

 

 

转载于:https://www.cnblogs.com/mengjinluohua/p/4990945.html

你可能感兴趣的文章
QML中的state 状态
查看>>
tomcat文件夹与文件解析
查看>>
consul如何限制注册的ip
查看>>
iOS开发中三种简单的动画设置
查看>>
ELK收集MySQL慢查询
查看>>
旋转数组
查看>>
2015 多校赛 第四场 1010 (hdu 5336)
查看>>
Day02 过滤和排序数据
查看>>
1043: [HAOI2008]下落的圆盘 - BZOJ
查看>>
CSS打造固定表头
查看>>
Activity管理类
查看>>
http缓存
查看>>
Luogu4022 CTSC2012熟悉的文章(广义后缀自动机+二分答案+动态规划+单调队列)
查看>>
java.lang.StringBuilder
查看>>
Net core 关于缓存的实现
查看>>
mysql的表和数据类型
查看>>
uva11988Broken Keeyboard(链表)
查看>>
Java线程池关闭1-shutdown和isTerminated<转>
查看>>
web安全学习第一周
查看>>
nginx的学习材料
查看>>