從方式來(lái)說(shuō),有四種符欠;
從保存地方來(lái)說(shuō)嫡霞,有三種。
方式分類法:
SQlite
SQLite是一個(gè)輕量級(jí)的數(shù)據(jù)庫(kù)背亥,支持基本SQL語(yǔ)法秒际,是常被采用的一種數(shù)據(jù)存儲(chǔ)方式悬赏。Android為此數(shù)據(jù)庫(kù)提供了一個(gè)名為SQLiteDatabase的類狡汉,封裝了一些操作數(shù)據(jù)庫(kù)的API。(增刪查減)
在我做的項(xiàng)目里闽颇,是通過(guò)HashMap形式將數(shù)據(jù)存儲(chǔ)下來(lái)盾戴。循環(huán)HashMap,將數(shù)據(jù)存入數(shù)據(jù)庫(kù)兵多,SharePreference
SharedPreferences 是Android 中的內(nèi)置API尖啡,它允許我們存取鍵值對(duì)形式的基礎(chǔ)類型數(shù)據(jù),像:boolean,float ,int , long , string 剩膘。
這些數(shù)據(jù)將會(huì)持久化的存在衅斩,即使你的應(yīng)用程序結(jié)束之后(注意:如果應(yīng)用從手機(jī)上寫(xiě)在掉后,該程序?qū)?yīng)的SharedPreferences將會(huì)消失怠褐,保存在路徑:/data/data/<package_name>/shared_prefs 目錄下畏梆。跟保存地方有關(guān)下面介紹)
除SQLite數(shù)據(jù)庫(kù)外,另一種常用的數(shù)據(jù)存儲(chǔ)方式奈懒,其本質(zhì)就是一個(gè)xml文件奠涌,常用于存儲(chǔ)較簡(jiǎn)單的,不會(huì)伴隨著程序結(jié)束而被清除的磷杏,參數(shù)溜畅,可以應(yīng)用之間共享(需要設(shè)置權(quán)限),但是建議用ContentProviderFile
即常說(shuō)的文件(I/O)存儲(chǔ)方法极祸,常用語(yǔ)存儲(chǔ)大數(shù)量的數(shù)據(jù)慈格,但是缺點(diǎn)是更新數(shù)據(jù)將是一件困難的事情。保存到SD卡中遥金,需要寫(xiě)入權(quán)限浴捆,應(yīng)用卸載之后數(shù)據(jù)仍在
在AndroidManifest.xml中加入訪問(wèn)SDCard的權(quán)限如下:
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
補(bǔ)充:Android6.0之后,會(huì)彈窗出來(lái)汰规,需要用戶授權(quán)
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
- ContentProvider
安卓四大組件之一汤功,系統(tǒng)專門(mén)開(kāi)辟一塊內(nèi)存保存數(shù)據(jù)用于提供給app使用,例如音頻溜哮,視頻滔金,圖片和通訊錄色解。每個(gè)Content Provider都會(huì)對(duì)外提供一個(gè)公共的URI(包裝成Uri對(duì)象),如果應(yīng)用程序有數(shù)據(jù)需要共享時(shí)餐茵,就需要使用Content Provider為這些數(shù)據(jù)定義一個(gè)URI科阎,然后其他的應(yīng)用程序就通過(guò)Content Provider傳入這個(gè)URI來(lái)對(duì)數(shù)據(jù)進(jìn)行操作。
PS: URI由3個(gè)部分組成:"content://"忿族、數(shù)據(jù)的路徑锣笨、標(biāo)識(shí)ID(可選)。
保存地方分類法:
- app分配的私有內(nèi)存:私有數(shù)據(jù)庫(kù)道批,SharePreference(其存儲(chǔ)位置在/data/data/<包名>/shared_prefs目錄下)错英。寫(xiě)入不需要向系統(tǒng)申請(qǐng)權(quán)限,讀取需要root隆豹,應(yīng)用卸載是被清除椭岩;
- app可以分配的sd里的內(nèi)存,也就是常常將系統(tǒng)一部分?jǐn)?shù)據(jù)移到sd卡里了璃赡,寫(xiě)入不需要權(quán)限判哥,讀取需要root,應(yīng)用卸載時(shí)被清除碉考;
- 系統(tǒng)sd卡儲(chǔ)存塌计,比如ContentProvider,F(xiàn)ile侯谁;寫(xiě)入需要權(quán)限锌仅,讀取不需要權(quán)限,應(yīng)用卸載時(shí)良蒸,不被清除技扼。
用法:
- SQlite
- 查
public static AAA queryAAACacheByKey(String key) {
try {
return db().find(Selector.from(AAA.class).where("tb_aaa_key", "=", key));
} catch (DbException e) {
UploadException.uploadInfo("queryAAACacheByKey : " + e.getMessage() + "\n key = " + key);
}
return null;
}
public Selector where(String columnName, String op, Object value) {//根據(jù)key(表名)找到selector
this.whereBuilder = WhereBuilder.b(columnName, op, value);
return this;
}
public <T> T find(Selector selector) throws DbException {
if (!tableIsExist(selector.getEntityType())) return null;
String sql = selector.limit(1).toString();
long seq = CursorUtils.FindCacheSequence.getSeq();
findTempCache.setSeq(seq);
Object obj = findTempCache.get(sql);
if (obj != null) {
return (T) obj;
}
//以上就是根據(jù)selector獲取字符串sql,先到cache去找有沒(méi)有嫩痰,沒(méi)有則接下來(lái)去數(shù)據(jù)庫(kù)查找內(nèi)容
Cursor cursor = execQuery(sql);
if (cursor != null) {
try {
if (cursor.moveToNext()) {
T entity = (T) CursorUtils.getEntity(this, cursor, selector.getEntityType(), seq);
findTempCache.put(sql, entity);//存入cache
return entity;
}
} catch (Throwable e) {
throw new DbException(e);
} finally {
closeQuietly(cursor);
}
}
return null;
}
Cursor對(duì)象可以理解為游標(biāo)對(duì)象剿吻,凡是對(duì)數(shù)據(jù)有所了解的人,相信對(duì)此對(duì)象都不會(huì)陌生串纺,在這里機(jī)不再累述丽旅。只提醒一點(diǎn),在第一次讀取Cursor對(duì)象中的數(shù)據(jù)時(shí)纺棺,一定要先移動(dòng)游標(biāo)榄笙,否則此游標(biāo)的位置在第一條記錄之前,會(huì)引發(fā)異常祷蝌。
public Cursor execQuery(String sql) throws DbException {
debugSql(sql);
try {
return database.rawQuery(sql, null);// 根據(jù)給定SQL茅撞,執(zhí)行查詢。
} catch (Throwable e) {
throw new DbException(e);
}
}
- 增
public void save(Object entity) throws DbException {
try {
beginTransaction();
createTableIfNotExist(entity.getClass());
execNonQuery(SqlInfoBuilder.buildInsertSqlInfo(this, entity));
setTransactionSuccessful();
} finally {
endTransaction();
}
}
- 刪
public void delete(Object entity) throws DbException {
if (!tableIsExist(entity.getClass())) return;
try {
beginTransaction();
execNonQuery(SqlInfoBuilder.buildDeleteSqlInfo(this, entity));
setTransactionSuccessful();
} finally {
endTransaction();
}
}
- 改
public void update(Object entity, String... updateColumnNames) throws DbException {
if (!tableIsExist(entity.getClass())) return;
try {
beginTransaction();
execNonQuery(SqlInfoBuilder.buildUpdateSqlInfo(this, entity, updateColumnNames));
setTransactionSuccessful();
} finally {
endTransaction();
}
}
- SharePreference
五種數(shù)據(jù)類型(boolean,int米丘,float剑令,long和String),只有存拄查。取吁津,刪
Context ctx = MainActivity.this;
SharedPreferences sp = ctx.getSharedPreferences("SP", MODE_PRIVATE);
//存入數(shù)據(jù)
Editor editor = sp.edit();
editor.putString("STRING_KEY", "string");
editor.putInt("INT_KEY", 0);
editor.putBoolean("BOOLEAN_KEY", true);
editor.commit();
//取出數(shù)據(jù)
editor.getBoolean(key, false);
editor.getInt(key, 0)堕扶;
//刪
editor.remove(key);
editor.commit();
//全刪
editor.clear().commit();
- File
- 存 (圖片舉例)
File imagefile;
for (int i = 0; i < num; i++) {
imagefile = new File(App.getInst().getCacheDir() +路徑名, img.get(i).id + ".png");
if (!imagefile.exists()) {//如果圖片不存在碍脏,則下載
DownloadImageUtils.getInstance().downLoadImage(img.get(i).image,img.get(i).id + ".png");
}
}
public void downLoadImage(String url, final String name) {
ImageRequest imageRequest = new ImageRequest(url,
new Response.Listener<Bitmap>() {
@Override
public void onResponse(Bitmap response) {
if (response != null) {
saveBitmap(response, name);
} else {
}
}
}, 0, 0, Bitmap.Config.ARGB_8888, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
}
});
mQueue.add(imageRequest);
}
private void saveBitmap(final Bitmap bitmap, final String name) {
new Thread(new Runnable() {
@Override
public void run() {
File file = new File(App.getInst().getCacheDir() +路徑名);
if (!file.exists()) {
file.mkdir();//Creates the directory named by this abstract pathname:app.getInst().getCacheDir()
}
File f = new File(App.getInst().getCacheDir() + 路徑名), name);
if (!f.exists()) {
try {
FileOutputStream out = new FileOutputStream(f);
bitmap.compress(Bitmap.CompressFormat.PNG, 90, out);//壓縮bitmap,否則很大
out.flush();
out.close();
} catch (FileNotFoundException e) {
} catch (IOException e) {
}
} else {
}
}
}).start();
}
我們可以理解File是一個(gè)路由稍算,可以根據(jù)路徑找到我們想要的文件(們)典尾;
- 讀
Bitmap bitmap = null;
try {
FileInputStream fis = new FileInputStream(getApplicationContext().getCacheDir() + name);
bitmap = BitmapFactory.decodeStream(fis);
} catch (Exception e) {
} catch (OutOfMemoryError e){
}
- ContentProvider
ContentProvider提供了一種統(tǒng)一的通過(guò)Uri實(shí)現(xiàn)數(shù)據(jù)操作的方式。其步驟為:
public class MyProvider extends ContentProvider{
@Override
public int delete(Uri uri, String selection, String[] selectionArgs) {
// TODO Auto-generated method stub
return 0;
}
@Override
public String getType(Uri uri) {
// TODO Auto-generated method stub
return null;
}
@Override
public Uri insert(Uri uri, ContentValues values) {
return null;
}
//在Create中初始化一個(gè)數(shù)據(jù)庫(kù)
@Override
public boolean onCreate() {
SQLiteDatabase db = this.getContext().openOrCreateDatabase("test_db.db3", Context.MODE_PRIVATE, null);
db.execSQL("create table tab(_id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL)");
ContentValues values = new ContentValues();
values.put("name", "test");
db.insert("tab", "_id", values);
db.close();
return true;
}
//實(shí)現(xiàn)query方法
@Override
public Cursor query(Uri uri, String[] projection, String selection,
String[] selectionArgs, String sortOrder) {
SQLiteDatabase db = this.getContext().openOrCreateDatabase("test_db.db3", Context.MODE_PRIVATE, null);
Cursor c = db.query("tab", null, null, null, null, null,null);
return c;
}
@Override
public int update(Uri uri, ContentValues values, String selection,
String[] selectionArgs) {
// TODO Auto-generated method stub
return 0;
}
}
- 在當(dāng)前應(yīng)用程序中定義一個(gè)ContentProvider邪蛔。
<provider android:name=".MyProvider" android:authorities="com.test.MyProvider"/>
- 在當(dāng)前應(yīng)用程序的AndroidManifest.xml中注冊(cè)此ContentProvider
public class MainActivity extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
//獲取上下文
Context ctx = MainActivity.this;
//獲取ContentResolver對(duì)象
ContentResolver resolver = ctx.getContentResolver();
//獲取Uri對(duì)象
Uri uri = Uri.parse("content://com.test.MyProvider");
//獲取數(shù)據(jù)
Cursor c = resolver.query(uri, null, null, null, null);
c.moveToFirst();
for(int i=0; i<c.getCount(); i++){
int index = c.getColumnIndexOrThrow("name");
String src = c.getString(index);
Log.d("", src);
c.moveToNext();
}
}
}
- 其他應(yīng)用程序通過(guò)ContentResolver和Uri來(lái)獲取此ContentProvider的數(shù)據(jù)急黎。