Android入門05 -- 數(shù)據(jù)存儲(chǔ)

  • Android的數(shù)據(jù)存儲(chǔ)方式有:SharedPreferences,F(xiàn)ile,SQLite缴淋,下面來詳細(xì)介紹每種數(shù)據(jù)存儲(chǔ)的特點(diǎn)與使用乖酬;

SharedPreferences

  • SharedPreferences是Android平臺(tái)上一個(gè)輕量級(jí)的數(shù)據(jù)存儲(chǔ)輔助類刨晴,用來保存應(yīng)用的一些常用配置,它提供了string空镜,set染厅,int,long泉哈,float蛉幸,boolean六種數(shù)據(jù)類型,最終數(shù)據(jù)是以xml形式進(jìn)行存儲(chǔ)丛晦,在應(yīng)用中通常做一些簡單數(shù)據(jù)的持久化緩存奕纫;
SharedPreferences的使用注意事項(xiàng):
  • 不要存放大的key和value在SharedPreferences中,否則會(huì)一直存儲(chǔ)在內(nèi)存中得不到釋放烫沙,內(nèi)存使用過高會(huì)頻發(fā)引發(fā)GC匹层,導(dǎo)致界面丟幀甚至ANR;
  • 不相關(guān)的配置選項(xiàng)最好不要放在一起锌蓄,單個(gè)文件越大讀取速度則越慢升筏;
  • 讀取頻繁的key和不頻繁的key盡量不要放在一起(如果整個(gè)文件本身就較小則忽略,為了這點(diǎn)性能添加維護(hù)得不償失)煤率;
  • 不要每次都edit仰冠,因?yàn)槊看味紩?huì)創(chuàng)建一個(gè)新的EditorImpl對(duì)象,最好是批量處理統(tǒng)一提交蝶糯,否則edit().commit每次創(chuàng)建一個(gè)EditorImpl對(duì)象并且進(jìn)行一次IO操作洋只,嚴(yán)重影響性能;
  • commit發(fā)生在UI線程中昼捍,apply發(fā)生在工作線程中识虚,對(duì)于數(shù)據(jù)的提交最好是批量操作統(tǒng)一提交,雖然apply發(fā)生在工作線程(不會(huì)因?yàn)镮O阻塞UI線程)但是如果添加任務(wù)較多也有可能帶來其他嚴(yán)重后果(參照ActivityThread源碼中handleStopActivity方法實(shí)現(xiàn))
  • 盡量不要存放json和html妒茬,這種可以直接文件緩存担锤;
  • SharedPreferences不能跨進(jìn)程通信 Context.PROCESS
  • 最好提前初始化SharedPreferences乍钻,避免第一次創(chuàng)建時(shí)讀取文件線程未結(jié)束而出現(xiàn)等待情況肛循;
SharedPreferences的創(chuàng)建
  • 創(chuàng)建SharedPreferences有兩種方式:
    • 第一種:調(diào)用Context對(duì)象的getSharedPreferences()方法铭腕;
    • 第二種:調(diào)用Activity對(duì)象的getPreferences()方法;
  • 區(qū)別在于:第一種方式獲得的可以被同一應(yīng)用程序下的組件共用多糠,但是第二種方式獲得的只可以在該Activity下使用累舷;
SharedPreferences的操作模式
  • MODE_PRIVATE:為默認(rèn)操作模式,代表該文件是私有數(shù)據(jù)夹孔,只能被應(yīng)用本身訪問被盈,在該模式下寫入的內(nèi)容會(huì)覆蓋原文件的內(nèi)容;
  • MODE_APPEND:檢查文件是否存在,存在就往文件追加內(nèi)容,否則就創(chuàng)建新文件搭伤;
  • MODE_WORLD_READABLE:表示當(dāng)前文件可以被其他應(yīng)用讀戎辉酢;
  • MODE_WORLD_WRITEABLE:表示當(dāng)前文件可以被其他應(yīng)用寫入怜俐;
SharedPreferences的增刪改查
  • 封裝成單例類SFSharedPreferences身堡,代碼實(shí)現(xiàn)如下:
package com.example.yyshop.general.database;

import android.content.Context;
import android.content.SharedPreferences;

import static android.content.Context.MODE_PRIVATE;

public class SFSharedPreferences {

    private static volatile SFSharedPreferences mInstance;
    private SharedPreferences sharedPreferences;
    private SharedPreferences.Editor editor;

    public static synchronized SFSharedPreferences getInstance(Context context){
        if (mInstance == null) {
            synchronized (SFSharedPreferences.class) {
                if (mInstance == null) {
                    mInstance = new SFSharedPreferences(context);
                }
            }
        }
        return mInstance;
    }

    private SFSharedPreferences(Context context){
        if (sharedPreferences == null) {
            //創(chuàng)建SharedPreferences實(shí)例對(duì)象
            sharedPreferences = context.getSharedPreferences("config",MODE_PRIVATE);
            editor = sharedPreferences.edit();
        }
    }

    //存儲(chǔ)數(shù)據(jù)
    public void save(String key,String data) {
        editor.putString(key,data);
        editor.commit();
    }

    //讀取數(shù)據(jù)
    public String read(String key){
        String data = sharedPreferences.getString(key,"");
        return data;
    }

    //刪除數(shù)據(jù)
    public void remove(String key) {
        editor.remove(key);
        editor.commit();
    }

    //清空所有數(shù)據(jù)
    public void clear() {
        editor.clear();
        editor.commit();
    }
}
  • 注意??:SharedPreferences在存儲(chǔ),刪除拍鲤,清空數(shù)據(jù)時(shí)盾沫,都是通過editor對(duì)象進(jìn)行操作的,且必須調(diào)用editor.commit()殿漠,進(jìn)行提交操作才能生效;
  • 外界調(diào)用代碼如下:
public class SFShopCarFragment extends SFBaseFragment {
    @Override
    protected void initUI() {
        Button button = find(R.id.shopcar_button);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(getActivity(), SFShopDetailActivity.class);
                startActivity(intent);

                SFSharedPreferences.getInstance(getContext()).save("name","yanzi");
                String name = SFSharedPreferences.getInstance(getActivity()).read("name");
                Log.i("SFShopCarFragment",name);
            }
        });
    }

    @Override
    protected int getLayoutId() {
        return R.layout.fragment_shopcar;
    }
}
  • SharedPreferences存儲(chǔ)數(shù)據(jù)的位置為:/data/data/項(xiàng)目包/shared_prefs/名稱.xml佩捞,可通過Device File Explore進(jìn)行查看绞幌,如下所示:
    image.png

SQLite數(shù)據(jù)庫

  • SQLite是一款輕量型數(shù)據(jù)庫,廣泛使用于移動(dòng)端一忱;
  • 在Android中莲蜘,系統(tǒng)封裝了一個(gè)SQLite數(shù)據(jù)庫的抽象類SQLiteOpenHelper,我們需要自定義一個(gè)子類繼承自抽象類SQLiteOpenHelper帘营,實(shí)現(xiàn)其相關(guān)的抽象方法票渠,然后進(jìn)行數(shù)據(jù)庫的增刪改查操作;
抽象類SQLiteOpenHelper的兩個(gè)抽象方法
  • 第一個(gè)抽象方法是:onCreate方法芬迄,在實(shí)例化繼承自SQLiteOpenHelper的子類時(shí)調(diào)用(創(chuàng)建數(shù)據(jù)庫時(shí))问顷,在這個(gè)方法中我們可進(jìn)行數(shù)據(jù)庫表的創(chuàng)建,此方法只會(huì)調(diào)用一次禀梳;
  • 第二個(gè)抽象方法是:onUpgrade方法杜窄,在數(shù)據(jù)庫升級(jí)時(shí)使用;
  • 有關(guān)數(shù)據(jù)庫的增刪改查操作算途,見如下代碼:
package com.example.yyshop.general.database;

import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;
import com.example.yyshop.home.model.SFGoodModel;
import java.util.ArrayList;
import java.util.List;

public class SFSQLShopCarHelper extends SQLiteOpenHelper {

    //數(shù)據(jù)庫版本號(hào)
    private static Integer Version = 1;

    //數(shù)據(jù)庫的名稱
    private static final String DATA_BASE_NAME = "shopcar.db";

    //購物車商品表
    private static final String SHOP_CAR_TABLE_NAME = "t_goods";

    //單例對(duì)象
    private static volatile SFSQLShopCarHelper mInstance;

    //在SQLiteOpenHelper的子類當(dāng)中塞耕,必須有該構(gòu)造函數(shù)
    private SFSQLShopCarHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version) {
        //必須通過super調(diào)用父類當(dāng)中的構(gòu)造函數(shù)
        super(context, name, factory, version);
    }

    private SFSQLShopCarHelper(Context context, String name, int version) {
        this(context,name,null,version);
    }

    private SFSQLShopCarHelper(Context context, String name) {
        this(context, name, Version);
    }

    private SFSQLShopCarHelper(Context context) {
        this(context,DATA_BASE_NAME);
    }

    public static synchronized SFSQLShopCarHelper getInstance(Context context) {
        if (mInstance == null) {
            synchronized (SFSharedPreferences.class) {
                if (mInstance == null) {
                    mInstance = new SFSQLShopCarHelper(context);
                }
            }
        }
        return mInstance;
    }

    @Override
    public void onCreate(SQLiteDatabase db) {
        Log.i("SFSQLShopCarHelper","開始創(chuàng)建數(shù)據(jù)庫表 t_shopCar");
        createTable(db);
        Log.i("SFSQLShopCarHelper","完成創(chuàng)建數(shù)據(jù)庫表 t_shopCar");
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        //數(shù)據(jù)庫升級(jí)

    }

    //創(chuàng)建表
    private void createTable(SQLiteDatabase database){
        String create_shop_car_goods = "create table if not exists " + SHOP_CAR_TABLE_NAME +"(id integer primary key autoincrement,goodId text,goodName text,goodPic text,goodPrice text)";
        try {
            database.execSQL(create_shop_car_goods);
        } catch (Exception e) {
            e.printStackTrace();
            Log.i("SFSQLShopCarHelper", "創(chuàng)表shop_car_goods -- 出現(xiàn)異常");
        };
    }

    //插入單條數(shù)據(jù)
    public void insert(SFGoodModel model){
        SQLiteDatabase database = getWritableDatabase();

        String goodId = model.getGoodsId();
        String goodName = model.getGoodsName();
        String goodPic = model.getComPic();
        String goodPrice = model.getPrice();

        String insert = "insert into " + SHOP_CAR_TABLE_NAME + "(goodId,goodName,goodPic,goodPrice)values" + "('"+goodId+"','"+goodName+"','"+goodPic+"','"+goodPrice+"')";
        database.execSQL(insert);
        Log.i("SFShopCarFragment",insert);
        Log.i("SFShopCarFragment","插入了1條數(shù)據(jù)");
        database.close();
    }

    //查詢所有商品
    public List<SFGoodModel> select(){
        SQLiteDatabase database = getReadableDatabase();
        List<SFGoodModel> models = new ArrayList<>();

        String select = "select * from " + SHOP_CAR_TABLE_NAME;
        Cursor cursor = database.rawQuery(select,null);

        while (cursor.moveToNext()) {
            String id = cursor.getString(cursor.getColumnIndex("id"));
            String goodName = cursor.getString(cursor.getColumnIndex("goodName"));
            String goodId = cursor.getString(cursor.getColumnIndex("goodId"));
            String goodPic = cursor.getString(cursor.getColumnIndex("goodPic"));
            String goodPrice = cursor.getString(cursor.getColumnIndex("goodPrice"));

            SFGoodModel model = new SFGoodModel();
            model.setGoodsId(goodId);
            model.setGoodsName(goodName);
            model.setGoodsId(goodPic);
            model.setGoodsId(goodPrice);
            models.add(model);
            Log.i("SFShopCarFragment", id + " " + goodName + " " + goodId + " " + goodPic + " " + goodPrice);
        }
        //關(guān)閉數(shù)據(jù)庫
        cursor.close();
        database.close();
        return models;
    }

    //刪除指定商品
    public void delete(SFGoodModel model) {
        SQLiteDatabase database = getReadableDatabase();
        String delete = "delete from " + SHOP_CAR_TABLE_NAME + " where goodid = '"+model.getGoodsId()+"'";
        try {
            database.execSQL(delete);
            Log.i("SFSQLShopCarHelper","成功刪除一條數(shù)據(jù)");
            database.close();
        } catch (Exception e) {
            e.printStackTrace();
            Log.i("SFSQLShopCarHelper", "刪除指定數(shù)據(jù) -- 出現(xiàn)異常");
            database.close();
        }
    }

    //刪除所有商品
    public void deleteAll(){
        SQLiteDatabase database = getReadableDatabase();
        String delete = "delete from " + SHOP_CAR_TABLE_NAME;
        try {
            database.execSQL(delete);
            Log.i("SFSQLShopCarHelper","成功刪除所有數(shù)據(jù)");
            database.close();
        } catch (Exception e) {
            e.printStackTrace();
            Log.i("SFSQLShopCarHelper", "刪除所有數(shù)據(jù) -- 出現(xiàn)異常");
            database.close();
        }
    }
}
  • 上述自定義子類SFSQLShopCarHelper繼承自SQLiteOpenHelper系統(tǒng)抽象類;
  • 在進(jìn)行數(shù)據(jù)庫的增刪改查時(shí)嘴瓤,首先是獲取database扫外,調(diào)用getReadableDatabase()或者getWritableDatabase()方法莉钙,相當(dāng)于打開數(shù)據(jù)庫,在執(zhí)行完數(shù)據(jù)庫的增刪改查操作之后筛谚,調(diào)用close()方法磁玉,關(guān)閉數(shù)據(jù)庫;
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末刻获,一起剝皮案震驚了整個(gè)濱河市蜀涨,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌蝎毡,老刑警劉巖厚柳,帶你破解...
    沈念sama閱讀 217,185評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異沐兵,居然都是意外死亡别垮,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,652評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門扎谎,熙熙樓的掌柜王于貴愁眉苦臉地迎上來碳想,“玉大人,你說我怎么就攤上這事毁靶‰时迹” “怎么了?”我有些...
    開封第一講書人閱讀 163,524評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵预吆,是天一觀的道長龙填。 經(jīng)常有香客問我,道長拐叉,這世上最難降的妖魔是什么岩遗? 我笑而不...
    開封第一講書人閱讀 58,339評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮凤瘦,結(jié)果婚禮上宿礁,老公的妹妹穿的比我還像新娘。我一直安慰自己蔬芥,他們只是感情好梆靖,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,387評(píng)論 6 391
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著笔诵,像睡著了一般涤姊。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上嗤放,一...
    開封第一講書人閱讀 51,287評(píng)論 1 301
  • 那天思喊,我揣著相機(jī)與錄音,去河邊找鬼次酌。 笑死恨课,一個(gè)胖子當(dāng)著我的面吹牛舆乔,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播剂公,決...
    沈念sama閱讀 40,130評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼希俩,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了纲辽?” 一聲冷哼從身側(cè)響起颜武,我...
    開封第一講書人閱讀 38,985評(píng)論 0 275
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎拖吼,沒想到半個(gè)月后鳞上,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,420評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡吊档,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,617評(píng)論 3 334
  • 正文 我和宋清朗相戀三年篙议,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片怠硼。...
    茶點(diǎn)故事閱讀 39,779評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡鬼贱,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出香璃,到底是詐尸還是另有隱情这难,我是刑警寧澤,帶...
    沈念sama閱讀 35,477評(píng)論 5 345
  • 正文 年R本政府宣布葡秒,位于F島的核電站雁佳,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏同云。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,088評(píng)論 3 328
  • 文/蒙蒙 一堵腹、第九天 我趴在偏房一處隱蔽的房頂上張望炸站。 院中可真熱鬧,春花似錦疚顷、人聲如沸旱易。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,716評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽阀坏。三九已至,卻和暖如春笆檀,著一層夾襖步出監(jiān)牢的瞬間忌堂,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,857評(píng)論 1 269
  • 我被黑心中介騙來泰國打工酗洒, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留士修,地道東北人枷遂。 一個(gè)月前我還...
    沈念sama閱讀 47,876評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像棋嘲,于是被迫代替她去往敵國和親酒唉。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,700評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容