Android-持久化技術(一)

文件存儲

文件存儲是android中最基本的數據存儲方式,不需要對存儲的內容作任何的格式化處理,所有的數據會被原封不動的保存到文件當中,比較適合存儲一些簡單的文本文件或者是二進制文件。下面我們看一個簡單的案例,分析存儲和讀取數據的具體實現。

將數據存儲到文件中

先看代碼:

        save.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                String data = "Data to save";

                FileOutputStream out = null;

                BufferedWriter bufferedWriter = null;

                try {

                    out = openFileOutput("data", Context.MODE_PRIVATE);

                    bufferedWriter = new BufferedWriter(new OutputStreamWriter(out));


                    bufferedWriter.write(data);

                    Toast.makeText(MainActivity.this,"數據存儲完成",0).show();

                }catch (Exception e){


                    e.printStackTrace();

                    Toast.makeText(MainActivity.this,"數據存儲失敗",0).show();

                }finally {

                    try {

                        if (bufferedWriter != null){

                            bufferedWriter.close();
                        }

                    }catch (Exception e){

                        e.printStackTrace();

                    }

                }

            }
        });

代碼分析:
通過openFileOutput()方法得到一個FileOutputStream對象,并依此構建OutputStreamWriter對象。然后借助OutputStreamWriter構建出BufferedWriter對象,通過BufferedWriter對象將文本內容寫入。

從文件中讀取數據

代碼如下:

        read.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                FileInputStream input = null;

                BufferedReader reader = null;

                StringBuilder content = new StringBuilder();

                try {

                    input = openFileInput("data");

                    reader = new BufferedReader(new InputStreamReader(input));

                    String line = "";

                    while ((line = reader.readLine()) != null){

                        content.append(line);

                    }

                }catch (Exception e){

                    e.printStackTrace();

                }finally {

                    try{

                        if (reader != null){

                            reader.close();

                        }

                    }catch (Exception e){

                    }
                }

                Toast.makeText(MainActivity.this, "文本內容" + content,0).show();
            }
        });

首先通過openFileInput("data")方法獲取到一個FileInputStream對象,然后借助它構建出一個InputStreamReader對象。我們就可以用過BufferedReader來逐行讀取文件中的內容。

SharedPreferences

不同于文件存儲方式,SharedPreferences是利用鍵值對來存儲數據的。我們只需要在存儲數據的時候,給本條數據對應的一個鍵值,則在去數據的時候就可以根據這個鍵來把值取出。
SharedPreferences支持多種不同類型的數據存儲。例如:字符串,布爾,整形等。

可存儲類型
使用SharedPreferences存儲數據

要想使用SharedPreferences來存儲數據,首先需要得到SharedPreferences對象。Android主要提供了3中方式用于得到SharedPreferences對象:
1、Context類的getSharedPreferences()
2、Activity的getPreferences()
3、PreferenceManager.getDefaultSharedPreferences()

主要實現步驟
1、調用SharedPreferences的edit()方法來獲取SharedPreferences.Editor對象
2、向Editor對象中添加數據。
3、調用Editor的apply()方法提交數據,完成數據存儲。

        spSave.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {


                SharedPreferences.Editor editor = getSharedPreferences("data",MODE_PRIVATE).edit();

                editor.putString("name","nameStr");

                editor.putInt("age", 20);

                editor.putBoolean("bool",false);

                editor.apply();
            }
        });
使用SharedPreferences讀取數據

SharedPreferences的讀取數據操作和其存儲數據操作對應的,使用get方法把對應類型的數據讀取出來相當的方便。android也為我們提供了讀取多種類型數據的方法。

SharedPreferences讀取數據

讀取數據的實現要比存取數據的實現還要簡單:

        spRead.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                SharedPreferences sp = getSharedPreferences("data",MODE_PRIVATE);

                String name = sp.getString("name","");

                Integer age = sp.getInt("age",0);

                Boolean bool = sp.getBoolean("bool",false);

                Log.d("MainActivity","name"+name+" age"+age+" bool"+bool);

            }
        });

SQLite數據庫存儲

SQLite是一款輕量級的關系型數據庫,它的運算速度非常快,占用內存非常少,在移動端上使用也相當適合的。那么android中的SQLite是如何使用的呢?

android為我們專門提供了一個SQLiteOpenHelper抽象類,用來管理數據庫,借助這個類就可以非常簡單的對數據庫進行創建和升級。
因為SQLiteOpenHelper是一個抽象類,我們需要創建一個自己的幫助類繼承它。

SQLiteOpenHelper中有兩個抽象方法:onCreate()和onUpgrade(),前者是實現數據庫創建,后者是實現數據庫升級的邏輯。
SQLiteOpenHelper還有兩個非常重要的實例方法:getWritableDatabase()和getReadableDatabase(),兩個方法都可以實現創建或者是打開一個現有數據庫(如果數據庫已經存在直接打開,如果數據庫不存在的話先創建一個新的數據庫),并返回一個可以對數據庫進行讀寫的對象。

但是不同的是當數據庫不可以寫入的時候(例如:磁盤已滿),getReadableDatabase()返回的數據庫將以只讀的方式打開數據庫,而getWritableDatabase()方法則會出現異常。

創建數據庫

我們下面嘗試一個實例,來理解數據庫的創建過程。

    public class MyDataBaseHelper extends SQLiteOpenHelper{

        //把建表語句定義成一個字符串常量
        public  static final String CREAT_BOOK = "create table Book("+
                "id integer primary key autoincrement, "+
                "auther text,"+"price real,"+"pages integer,"+
                "name text)";

        private Context mContext;

        public MyDataBaseHelper(Context context,String name,SQLiteDatabase.CursorFactory factory,int version){

            super(context,name,factory,version);

            mContext = context;

        }

        @Override
        public void onCreate(SQLiteDatabase sqLiteDatabase) {

            //execSQL()完成執行語句操作(建表)
            sqLiteDatabase.execSQL(CREAT_BOOK);

            Toast.makeText(MainActivity.this,"create successed",Toast.LENGTH_SHORT).show();

        }
        
        //升級數據庫
        //onUpgrade()方法主要用于對數據庫進行升級
        @Override
        public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
        }
    }

緊接著,我們在MainActivity類中聲明一個按鈕createTable和helper。

private Button createTable;
private MyDataBaseHelper helper;

并在MainActivity的onCreate()方法中初始化

    createTable = (Button)findViewById(R.id.button05);
    helper = new MyDataBaseHelper(this,"BookStore.db",null,1);

按鈕點擊

        createTable.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                helper.getWritableDatabase();
            }
        });

針對以上代碼:onCreate()方法中構建MyDataBaseHelper對象,通過構造函數將數據庫名指定為BookStore.db指定數據庫版本號為1,我們在createTable按鈕的點擊事件中調用getWritableDatabase()方法,即按鈕在第一次點擊的時候會首先判斷BookStore.db數據庫屬否存在,不存在會創建BookStore.db數據庫并調用MyDataBaseHelper的onCreate()方法, 如此一來Book表就能創建成功了,當我們在此點擊按鈕的時候就不會再創建數據庫了

升級數據庫

假如有這樣一種情況,現有的數據庫不能滿足我們的需求了,我們現在需要在原有數據庫的基礎上加一張表,在這里以Category表為例。
我們在MyDataBaseHelper類中聲明:

public  static final String CREAT_CATEGORY = "create table Category("+
                "id integer primary key autoincrement, "+
                "category_name text,"+"category_code integer)";

與此同時修改其onCreate()方法中的內容為

        @Override
        public void onCreate(SQLiteDatabase sqLiteDatabase) {
            //execSQL()完成執行語句操作(建表)
            sqLiteDatabase.execSQL(CREAT_BOOK);
            sqLiteDatabase.execSQL(CREAT_CATEGORY);
            Toast.makeText(MainActivity.this,"create successed",Toast.LENGTH_SHORT).show();
        }

點擊創建數據庫的按鈕,結果并沒有創建成功,因為數據庫已經存在了,onCreate()方法并未執行。那么怎么解決呢?其實啊,我們只需要利用MyDataBaseHelper的升級功能,調用onUpgrade()方法執行一些操作,就能輕松解決這個問題。

        @Override
        public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {

            sqLiteDatabase.execSQL("drop table if exists Book");

            sqLiteDatabase.execSQL("drop table if exists Category");

            onCreate(sqLiteDatabase);
        }

但是怎樣才能啟動onUpgrade()方法的執行呢?我們只需要在獲取MyDataBaseHelper對象的時候,設置數據庫的版本比之前的版本號大就OK了。

helper = new MyDataBaseHelper(this,"BookStore.db",null,2);
以上工作完成我們就實現了數據庫的升級。

增、刪、改、查

其實研究數據庫是為我們服務的。能夠實現數據的增、刪、改、查才是我們最終的目的。其實利用SQLIte數據庫實現增刪改查的功能也是相當的簡單。

        //向SQLite數據庫添加數據
        insert.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                SQLiteDatabase db = helper.getWritableDatabase();

                ContentValues values = new ContentValues();

                values.put("name","liu gaojian");
                values.put("auther","gu hongjuan");
                values.put("pages",770);
                values.put("price",36.5);

                db.insert("Book",null,values);
                values.clear();

                values.put("name","zhao si");
                values.put("auther","liu neng");
                values.put("pages",520);
                values.put("price",1.5);

                db.insert("Book",null,values);

                Toast.makeText(MainActivity.this,"add data successed",Toast.LENGTH_SHORT).show();

            }
        });


        //更新數據
        update.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                SQLiteDatabase db = helper.getWritableDatabase();

                ContentValues values = new ContentValues();

                values.put("price",66.6);

                db.update("Book",values,"name = ?",new String[]{"zhao si"});

                Toast.makeText(MainActivity.this,"update data successed",Toast.LENGTH_SHORT).show();

            }
        });



        //刪除數據
        delete.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                SQLiteDatabase db = helper.getWritableDatabase();

                db.delete("Book","pages > ?",new String[]{"600"});

                Toast.makeText(MainActivity.this,"delete data successed",Toast.LENGTH_SHORT).show();

            }
        });



        //查詢數據
        select.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {

                SQLiteDatabase db = helper.getWritableDatabase();

                //查詢db中的所有數據
                Cursor cursor = db.query("Book",null,null,null,null,null,null);

                if (cursor.moveToFirst()){

                    do {

                        //遍歷cursor對象,取出數據并打印
                        String name = cursor.getString(cursor.getColumnIndex("name"));

                        String auther = cursor.getString(cursor.getColumnIndex("auther"));

                        int pages = cursor.getInt(cursor.getColumnIndex("pages"));

                        double price = cursor.getDouble(cursor.getColumnIndex("pages"));

                        Toast.makeText(MainActivity.this, "name:"+name+"auther: "+auther+"pages:"+pages+"price:"+price, Toast.LENGTH_SHORT).show();


                    }while (cursor.moveToNext());

                }
                cursor.close();
            }
        });

針對以上代碼不做過多的解釋,只提一點就是我們在進行查詢操作的時候會用到query()方法,它有很多個參數,那么每個參數代表什么意義呢?

query方法的參數解釋
直接使用SQL操作數據庫

一些牛逼的人都是直接通過SQL操作數據庫。下面我們舉個簡單的例子來看一下直接利用SQL是如何操作數據庫的。

        select.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {


                SQLiteDatabase db = helper.getWritableDatabase();

                //添加數據
                db.execSQL("insert into Book (name, auther, pages, price) values(?, ?, ?, ?)", new String[]{"C語言","王二麻子", "334", "48.5"});
                db.execSQL("insert into Book (name, auther, pages, price) values(?, ?, ?, ?)", new String[]{"數據結構","習近平", "256", "49.9"});


                //更新數據
                db.execSQL("update Book set price = ? where name = ? ", new String[]{"5.49", "C語言"});


                //刪除數據
                db.execSQL("delete from Book where pages > ?", new String[]{"500"});

                //查詢數據
                db.rawQuery("select * from Book",null);

            }
        });
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,565評論 6 539
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,115評論 3 423
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,577評論 0 382
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,514評論 1 316
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,234評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,621評論 1 326
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,641評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,822評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,380評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,128評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,319評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,879評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,548評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,970評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,229評論 1 291
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,048評論 3 397
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,285評論 2 376