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


    我们都知道,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这个方法,才会在系统内存有数据库。

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

  • 相关阅读:
    javascript异步编程系列【十】—Jscex+Easeljs制作坦克大战
    博客园分页JQuery打造的分页无刷新的Repeater
    参赛作品
    摄像机、投影、3D旋转、缩放
    javascript异步编程系列【八】Jscex版火拼俄罗斯
    javascript异步编程系列【七】扫盲,我们为什么要用Jscex
    javascript异步编程系列【五】Jscex制作愤怒的小鸟
    javascript异步编程系列【六】Jscex版愤怒的小鸟之冲锋陷阵鸟
    每周优秀代码赏析—Jscex内核【一】
    javascript异步编程系列【一】用Jscex画圆
  • 原文地址:https://www.cnblogs.com/to-creat/p/5670732.html
Copyright © 2020-2023  润新知