当前位置: 代码迷 >> SQL >> 由sqlite在手机上的存储位置,引发的onCreate在哪里执行的小结
  详细解决方案

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

热度:72   发布时间:2016-05-05 10:18:44.0
由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这个方法,才会在系统内存有数据库。


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



  相关解决方案