zoukankan      html  css  js  c++  java
  • 使用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  

     

     

     

  • 相关阅读:
    不用google 是不行的
    一些主题
    腾讯cdc空间
    断言assert的使用
    malloc()和free()的相关知识
    linux上面的sz,rz命令与ssh的配合
    寻找第k小的元素
    c语言中字符串处理函数
    详解之#ifdef和#ifndef
    搭建测试环境linux静态链接库与动态链接库的区别及动态库的创建
  • 原文地址:https://www.cnblogs.com/mengjinluohua/p/4990945.html
Copyright © 2011-2022 走看看