由sqlite在手机上的存储位置,引发的onCreate在哪里执行的总结

转载请注明出处,谢谢:http://blog.csdn.net/harryweasley/article/details/46467495

我们都知道,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);
	}

	@Override
	public 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)");
	}

	@Override
	public 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,则没有数据库,返回false
		return 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);
    }

    @Override
    public void onCreate(SQLiteDatabase db)
    {
        executeAssetsSQL(db, "geocoding_create.sql");
    }

    @Override
    public 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 block
            e.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这个方法,才会在系统内存有数据库。

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

时间: 2024-10-13 01:21:29

由sqlite在手机上的存储位置,引发的onCreate在哪里执行的总结的相关文章

SharedPreferences数据、openFileOutput文件、SQLite数据库文件存储位置

在模拟器中: SharedPreferences将XML文件保存在/data/data/<package name>/shared_prefs目录下, openFileOutput方法将文件保存在/data/data/<package name>/files目录下 SQLite数据库文件存放在/data/data/<package name>/databases目录下 SharedPreferences数据.openFileOutput文件.SQLite数据库文件存储位

如何正确地在手机上显示图片——QImage与QPixmap完全解析

引言 用Qt程序在手机上显示一幅图片对编程人员来说是再基础不过的一件事情了.那么先让大家看两段代码: //dangerous should not be used, cannot display earth.png, //but if we change earth.png to a smaller image e.g. apple.png, apple.png can be displayed QPixmap pixmap; pixmap.load( ":/pics/earth.png&quo

构建安全的Xml Web Service系列之wse之证书存储位置

原文:构建安全的Xml Web Service系列之wse之证书存储位置 我们在前几天对xml web service的安全性提出了一些建议,大家可以通过以下地址访问: 构建安全的Xml Web Service系列之初探使用Soap头 构建安全的Xml Web Service系列之如何察看SoapMessage 构建安全的Xml Web Service系列之SSL篇 我曾经在上面几篇文章中承诺过要写一些有关wse3.0的,可一直没有时间,自身对wse3.0的认识也是非常有限,所以一直没有实现诺言

fastclick与zepto的 tap事件关于在手机上click事件的300ms延迟的区别

之前翻译过一篇关于fastclick的快速点击文章http://www.cnblogs.com/lilyimage/p/3568773.html,fastclick可以解决在手机上点击事件的300ms延迟:另外我们也知道zepto的touch模块,帮助我们实现了很多手机上的事件,比如tap等,tap事件也是为了解决在click的延迟问题.那么他们有什么区别呢? 先看zepto的touch模块实现: 1 $(document) 2 .on('touchstart ...',function(e){

如何在手机上跑深度神经网络

这天,老板跟你说,希望能在手机上跑深度神经网络,并且准确率要和 VGG.GoogleNet 差不多. 接到这个任务后你有点懵逼,这些网络别说计算量大,就连网络参数也要 100MB 的空间才存得下,放在手机上跑?开玩笑呗. 老板又说,怎么实现是你的事,我要的只是这个功能. 你默默地点了点头. 初步尝试:MobileNet v1 问题出在哪 要在手机上跑深度网络,需要在模型参数和计算量上进行优化. 那深度神经网络的计算量和参数量主要体现在哪呢?这里以 VGG16 为例: 第一层卷积: [224 x

CAD怎么快速查看图纸?怎么在手机上查看CAD图纸?

CAD怎么快速查看图纸?怎么在手机上查看图纸?相信不少小伙伴都会有这样 的疑问!其实,除了在PC端查看图纸,我们也可以在手机上查看CAD图纸,也是十分方便的! 我们都知道的,由于CAD图纸格式的特殊性,以至于CAD图纸不能很好地在其他的软件中对图纸进行查看,这时如果我们想对图纸进行查看,就需要为其营造一个适合的环境,通俗的说呢就是需要使用特定的软件了! 具体怎么操作呢?CAD怎么快速查看图纸?怎么在手机上查看图纸?操作方法如下: 1.在手机上安装CAD看图APP.(个人比较推荐使用迅捷CAD看图

Openerp 7.0 附件存储位置

? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58         我们知道对OpenERP中的每个内部对象(比如:业务伙伴,采购订单,销售订单,发货单,等等)我们都可以添加任意的附件,如图片,文档,视频等.那么这些附

匹夫细说C#:不是“栈类型”的值类型,从生命周期聊存储位置

匹夫细说C#:不是"栈类型"的值类型,从生命周期聊存储位置 c#语言规范 阅读目录 0x00 前言: 0x01 堆vs栈? 0x02 谁"能"使用栈? 0x03 结论 0x04 后记补充 回到目录 0x00 前言: 匹夫在日常和别人交流的时候,常常会发现一旦讨论涉及到"类型",话题的热度就会立马升温,因为很多似是而非.或者片面的概念常常被人们当做是全面和正确的答案.加之最近在园子看到有人翻译的<C#堆vs栈>系列,觉得也挺有趣,挺不错

transform:rotate在手机上显示有锯齿的解决方案

transform:rotate 属于简单好用的效果,但在手机上显示时,会有比较明显锯齿. 解决方案也很简单, 利用外层容器的overflow:hidden 加上图片margin:-1px 就可以解决. 原理没去深究,理论上是矢量跟位图的处理不一样,这个方案也有个小问题 就是图片变小了 ^_^ 可以用手机看看demo http://labs.aoao.org.cn/demo/transform-rotate/ update: 大家反应这方案在电脑上反而会出问题. 我测试了个新的方案rotate3