由sqlite在手機上的儲存位置,引發的onCreate在哪裡執行的總結,sqliteoncreate

來源:互聯網
上載者:User

由sqlite在手機上的儲存位置,引發的onCreate在哪裡執行的總結,sqliteoncreate

轉載請註明出處,謝謝: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);}@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">MessageDataBasemessageDataBase = 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);    }    @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這個方法,才會在系統記憶體有資料庫。


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



聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.