- 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)行查看绞幌,如下所示:
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ù)庫;