我们都知道,android为了操作数据库,一般是继承SQLiteOpenHelper类,并实现他的三个函数。

如下所示:

package jz.his.db;import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.database.sqlite.SQLiteOpenHelper;public class MessageDataBase extends SQLiteOpenHelper {public MessageDataBase(Context context, String name, CursorFactory factory,int version) {super(context, name, factory, version);}@Overridepublic void onCreate(SQLiteDatabase db) {db.execSQL("create table lgx_table(_id integer primary key autoincrement ," +"name varchar(20),content varchar(40),time varchar(20) ,head varchar(20),isCheck byte)");}@Overridepublic void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {}}
</pre><p>可以看到创建了一个名为lgx_table的表,里面有一id,name,content等列。</p><p></p>然后在Activity里,通过getWritableDatabase或者getReadableDatabase()方法来实例化一个SQLiteDatabase<p></p><p></p><pre name="code" class="java">MessageDataBase    messageDataBase = new MessageDataBase(context, "lgx", null, 1);SQLiteDatabase database = messageDataBase.getWritableDatabase();

我们可以看到,创建了一个名字为“lgx”的数据库。

这里提出一个问题,通过以上的步骤后,数据库保存在哪里了呢?

数据库保存在data/data/[your packageName]/databses,

1.如果是模拟器,直接通过Eclipse下,通过这样的步骤去看  DBMS--->File Explorer-->data---->data--->your packageName

网上很多介绍,我这里不介绍。

2.如果是真机,首先这个真机是root过了,下载一个Root Explorer。我的测试机是华为荣耀3c。

当我们执行完了以上的步骤后,进入data/data/jz.his.jzhis/databases/会看到这样的情景。

其实lgx就是我们刚刚创建的数据库,lgx-journal是数据库日志。

现在我们知道了,数据库存储的位置了,你以为这就是我写这篇博客的目的?继续往下看吧,嘿嘿。

如果我不想再手机系统内存中保存数据库,而是想将我的数据库放在手机sd卡中,那应该怎么做呢。

首先,我在res/raw中放一个现成的数据库,待会在代码里,将它拷入手机sd卡中。

看下面的代码:

package com.example.province;import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.database.sqlite.SQLiteException;
import android.database.sqlite.SQLiteOpenHelper;
import android.os.Environment;public class CopyOfCityInfoDataSupport2 {private static CopyOfCityInfoDataSupport2 cityInfoDataSupport;/*** 数据库在手机里的路径*/private static String DATABASE_PATH = Environment.getExternalStorageDirectory() + "/aaaaa/";/*** 数据库的名称*/public static final String dbName = "mzk_db";private SQLiteDatabase mSDB;public static CopyOfCityInfoDataSupport2 getInstance(Context context) {initDataBase(context);if (cityInfoDataSupport == null) {cityInfoDataSupport = new CopyOfCityInfoDataSupport2();}return cityInfoDataSupport;}/*** 初试化数据库*/private static void initDataBase(Context context) {boolean dbExist = checkDataBase();if (dbExist) {} else {// 如果不存在,则将raw里的数据存入手机sd卡copyDataBase(context);}}/*** 复制数据库到手机指定文件夹下* * @throws IOException*/private static void copyDataBase(Context context) {String databaseFilenames = DATABASE_PATH + dbName;File dir = new File(DATABASE_PATH);FileOutputStream os = null;InputStream is = null;// 判断文件夹是否存在,不存在就创建一个if (!dir.exists()) {dir.mkdirs();}try {// 得到数据库的输出流os = new FileOutputStream(databaseFilenames);// 得到数据文件的输入流is = context.getResources().openRawResource(R.raw.mzk_db);byte[] buffer = new byte[8192];int count = 0;while ((count = is.read(buffer)) != -1) {os.write(buffer, 0, count);os.flush();}// 之所以不在这里初始化,是因为这边是静态的方法,而mSDB并没有设置为静态的,也不推荐设为静态的// mSDB = SQLiteDatabase.openOrCreateDatabase(DATABASE_PATH +// dbName, null);} catch (Exception e) {e.printStackTrace();} finally {try {os.close();is.close();} catch (IOException e) {e.printStackTrace();}}}/*** 判断数据库是否存在* * @return*/private static boolean checkDataBase() {SQLiteDatabase checkDB = null;String databaseFilename = DATABASE_PATH + dbName;// 要自己加上try catch方法try {// 返回最新的数据库checkDB = SQLiteDatabase.openDatabase(databaseFilename, null,SQLiteDatabase.OPEN_READONLY);} catch (SQLiteException e) {// TODO: handle exception}if (checkDB != null) {checkDB.close();}// 如果checkDB为null,则没有数据库,返回falsereturn checkDB == null ? false : true;}/*** 查询所有省份的信息* * @return 省份信息*/public ArrayList<City> queryProvince() {// 创建数据库的实例mSDB = SQLiteDatabase.openOrCreateDatabase(DATABASE_PATH + dbName, null);ArrayList<City> list = new ArrayList<City>();String sql = "select * from fs_province";Cursor cursor = mSDB.rawQuery(sql, null);while (cursor.moveToNext()) {City city = new City();String id = cursor.getString(cursor.getColumnIndex("ProvinceID"));String name = cursor.getString(cursor.getColumnIndex("ProvinceName"));city.setName(name);city.setId(id);list.add(city);}if (cursor != null) {cursor.close();}return list;}public void closeDataBase() {if (mSDB != null) {mSDB.close();}}
}

我们看到,如果将数据库写到手机sd卡中,都不需要SQLiteOpenHelper类了,而是直接通过

mSDB = SQLiteDatabase.openOrCreateDatabase(DATABASE_PATH + dbName, null);就可以获得数据库的实例了。

但是这个方法有个缺点,就是不能进行数据库的升级了。显然这样是非常不好的。

那么如果我们还想用SQLiteOpenHelper,又将其写到sd卡中,又该怎么做呢。

下面的这段代码是有错误的,你只需要注意看51行,正是因为下面的代码,我才研究了onCreate方法到底什么时候执行。

package jz.his.db;import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;import jz.his.jzhis.R;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteException;
import android.database.sqlite.SQLiteOpenHelper;
import android.os.Environment;
import android.util.Log;public class CityInfoDataSupport extends SQLiteOpenHelper
{private final static String TAG = "CityInfoDataSupport";public static final String dbName = "cityego";// 数据库在手机里的路径private static String DATABASE_PATH = Environment.getExternalStorageDirectory().getAbsolutePath()+"/com.bcinfo.pwzs/";private static int version = 1;private final String GEOCODING_TABLE_NAME = "GEOCODING";private SQLiteDatabase mSDB = getReadableDatabase();private static CityInfoDataSupport mDataSupport;Context context;public static CityInfoDataSupport getInstance(Context context){initDatabse(context);if (mDataSupport == null){mDataSupport = new CityInfoDataSupport(context);}return mDataSupport;}CityInfoDataSupport(Context context){super(context, DATABASE_PATH+dbName, null, version);}@Overridepublic void onCreate(SQLiteDatabase db){executeAssetsSQL(db, "geocoding_create.sql");}@Overridepublic void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion){String sql = "drop table if exits " + GEOCODING_TABLE_NAME;db.execSQL(sql);onCreate(db);}private void loadSql(SQLiteDatabase db, String schemaName){InputStream inputS;try{inputS = context.getAssets().open(schemaName);BufferedReader reader = new BufferedReader(new InputStreamReader(inputS));String sql = null;while ((sql = reader.readLine()) != null){db.execSQL(sql.replace(";", ""));}reader.close();reader = null;}catch (IOException e){// TODO Auto-generated catch blocke.printStackTrace();}}/*** 读取数据库文件(.sql),并执行sql语句* */private void executeAssetsSQL(SQLiteDatabase db, String schemaName){Log.e("DataSupport", "executeAssetsSQL");BufferedReader in = null;try{in = new BufferedReader(new InputStreamReader(context.getAssets().open(schemaName)));String line;String buffer = "";while ((line = in.readLine()) != null){buffer += line;if (line.trim().endsWith(";")){db.execSQL(buffer.replace(";", ""));buffer = "";}}}catch (IOException e){Log.e("db-error", e.toString());}finally{try{if (in != null)in.close();}catch (IOException e){Log.e("db-error", e.toString());}}}public synchronized void insertCityInfo(){loadSql(mSDB, "geocoding_data.txt");}public synchronized List<City> queryDataById(String field, String id){String sql = "";List<City> cityList = new ArrayList<City>();if (field.equals("grade")){sql = "select * from  " + GEOCODING_TABLE_NAME + "  where grade = ? ";}else if (field.equals("parent")){sql = "select * from  " + GEOCODING_TABLE_NAME + "  where parent = ? ";}String[] params = new String[]{ id };Cursor c = mSDB.rawQuery(sql, params);while (c.moveToNext()){City city = new City();city.setGbCode(c.getString(c.getColumnIndex("gbcode")));city.setGbName(c.getString(c.getColumnIndex("gbname")));city.setGrade(c.getString(c.getColumnIndex("grade")));city.setLongitude(c.getString(c.getColumnIndex("longtitude")));city.setLatitude(c.getString(c.getColumnIndex("latitude")));city.setParent(c.getString(c.getColumnIndex("parent")));cityList.add(city);}if (c != null){c.close();}return cityList;}public void deleteAppTempTraffic(){String sql = "delete from " + GEOCODING_TABLE_NAME;mSDB.execSQL(sql);}public static void initDatabse(Context cntext){boolean dbExist = checkDataBase();//判断数据库是否存在 不存在就把raw里的数据库写入手机if (!dbExist){try{copyDataBase(cntext);}catch (IOException e){throw new Error("Error copying database");}}}/*** 判断数据库是否存在* @return false or true*/public static boolean checkDataBase(){SQLiteDatabase checkDB = null;try{String databaseFilename = DATABASE_PATH + dbName;checkDB = SQLiteDatabase.openDatabase(databaseFilename, null, SQLiteDatabase.OPEN_READONLY);}catch (SQLiteException e){}if (checkDB != null){checkDB.close();}return checkDB != null ? true : false;}/*** 复制数据库到手机指定文件夹下* @throws IOException*/public static void copyDataBase(Context context) throws IOException{String databaseFilenames = DATABASE_PATH + dbName;File dir = new File(DATABASE_PATH);FileOutputStream os = null;// 判断文件夹是否存在,不存在就新建一个if (!dir.exists()){dir.mkdirs();}try{// 得到数据库文件的写入流os = new FileOutputStream(databaseFilenames);}catch (FileNotFoundException e){e.printStackTrace();}// 得到数据库文件的数据流InputStream is = context.getResources().openRawResource(R.raw.cityego);byte[] buffer = new byte[8192];int count = 0;try{while ((count = is.read(buffer)) > 0){os.write(buffer, 0, count);os.flush();}}catch (IOException e){}try{is.close();os.close();}catch (IOException e){e.printStackTrace();}}
}

通过上面的这个代码,我的onCreate方法一直没有执行。最终经过我多次试验,我知道了问题所在,所以在这里进行总结。

那么onCreate方法到底什么时候执行呢?

SQLiteOpenHelper的onCreate方法一定是在getReadableDatabase方法之后的

SQLiteDatabase mSDB = getReadableDatabase()这个方法首先检查手机中,是否有已经存在的数据库,如果没有,则执行onCreate方法,如果有,则不执行---->但是,这里有个前提是,你的supre(context, DATABASE_PATH+dbName, null, version),的第二个参数不能是已存在的数据库路径。

我这里,将第二个参数,弄成了已存在的数据库文件,所以onCreate方法永远不会执行。

那么当super(context, dbName, null, version);第二个参数正确和并且执行了getReadableDatabase这个方法,才会在系统内存有数据库。

折磨了我一个下午啊啊啊啊。

由sqlite在手机上的存储位置,引发的onCreate在哪里执行的小结相关推荐

  1. Windows便笺(win10,win7便笺存储位置,恢复便笺数据)

    Windows便笺(Sticky Note) Win10 存储位置 %LocalAppData%\Packages\Microsoft.MicrosoftStickyNotes_8wekyb3d8bb ...

  2. android指定sqlite路径_android sqlite 存储位置

    Android 开发中使用 SQLite 数据库 SQLite 是一款非常流行的嵌入式数据库,它支持 SQL 查询,并且只用很少的内存.Android 在运行时集成了 SQLite,所以每个 Andr ...

  3. android 定位信息存哪,安卓手机便签系统存储位置在哪

    安卓手机便签系统存储位置在哪 2020-05-18 20:20:37 0点赞 0收藏 0评论 朋友送了我一部苹果手机,我终于可以把屏幕已经碎了的旧手机换掉了,只是旧手机备忘录中记着的诸多便签内容让我十 ...

  4. 利用Termux在手机上运行Linux系统

    1.下载Termux并安装 手机应用商店有的可以直接下载,还可以百度Termux,进入如下网页,选择在F-Droid进行下载 安装后界面 2.在Termux中输入以下命令 bash -c " ...

  5. 手机上怎么打开html游戏,怎么在手机上打开HTML文件怎么打开

    2 回答 2021-05-06 浏览:4 分类:其他问题 回答: HTML文件可以用手机浏览器打开. 从本质上来说,Internet( 互联网)是一个由一系列传输协议和各类文档所组成的集合,HTML文 ...

  6. AAAI 2021 | 在手机上实现19FPS实时的YOLObile目标检测

    作者|机器之心编辑部 来源|机器之心 本文提出了一套模型压缩和编译结合的目标检测加速框架,根据编译器的硬件特性而设计的剪枝策略能够在维持高 mAP 的同时大大提高运行速度,压缩了 14 倍的 YOLO ...

  7. vconsole 调试 查看LOG VUE在手机上调试 手机查看h5的日志

    简单介绍下vConsole: vConsole是一个由微信公众平台前端团队研发的web前端开发者面板,可用于展示console日志,方便开发.调试. 使用场景1,在vue-cli 构建的项目中使用: ...

  8. 教程 | 如何在手机上使用TensorFlow

    翻译 | AI科技大本营 参与 | zzq 审校 | reason_W 我们知道,TensorFlow是一个深度学习框架,它通常用来在服务器上训练需要大量数据的大模型.随着智能手机的普及,人们也越来越 ...

  9. python手机版怎么用-QPython,一个在手机上运行Python的神器

    之前安利过一款手机上运行Python的神器Termux,不过Termux的使用比较重,它实际是一款linux系统模拟器,安装好Termux后还要再安装python,并且是全命令行操作,一些读者使用起来 ...

  10. qpython手机版-QPython,一个在手机上运行Python的神器

    之前安利过一款手机上运行Python的神器Termux,不过Termux的使用比较重,它实际是一款linux系统模拟器,安装好Termux后还要再安装python,并且是全命令行操作,一些读者使用起来 ...

最新文章

  1. 美国的工资、俄罗斯的妻子、英国的房子、中国的饮食
  2. Java并发编程基础--ThreadLocal
  3. Google Chrome 最新市场份额
  4. java lbs_在 Java 中利用 redis 实现 LBS 服务
  5. Leetcode10. Regular Expression Matching
  6. vmware player 坑
  7. 【优化部署】基于matlab粒子群算法求解无线传感器WSN部署优化问题【含Matlab源码 1691期】
  8. Excel写批量代码(一)
  9. 程序员接私活常用平台汇总!
  10. 【Arduino】步进电机驱动程序Stepper_Motor_TB6600
  11. java crm系统_基于SSM框架开发的CRM系统
  12. hdu 6638 Snowy Smile 线段树维护最大子段和
  13. 一家计算机专卖店A型计算器,A型计算器谱子 | 手游网游页游攻略大全
  14. SpringBoot源码解析(十一)自定义banner
  15. WarShall算法求传递闭包(可达矩阵)
  16. Kali linux2020.4下载与安装教程(超级详细)
  17. 计算机网络面试题 43问汇总,面试必问
  18. Qt之QSqlDatabase 添加自定义物理键盘输入法
  19. php 如何执行top命令,技术|如何在批处理模式下运行 top 命令
  20. Cris 带你快速入门 Flink

热门文章

  1. 【购买ipad 2021记录:Apple官网线上下单,直营店线下取货】
  2. 计算机excel函数lookup,详细介绍数据查找VLookup函数在Excel中的应用举例
  3. c语言程序不知道头结点输出链表,C语言,不带头结点的链表,利用头插法存入信息,然后输出,没有error,却运行不了,求大神指点...
  4. mysql contain和like_mysql不带%的like 与等号之间的区别
  5. 深交所互动平台_是否存以互动平台回复替代公告、炒作股价的情形?容大感光收深交所关注函...
  6. ES6新特性总结 一
  7. 《用户至上:用户研究方法与实践》道德与法律问题
  8. 神秘的 shadow-dom 浅析
  9. angualrjs学习总结二(作用域、控制器、过滤器)
  10. 同济大学软件学院院长谈嵌入式方向选择