安卓 數(shù)據(jù)保存方式

從方式來(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)限),但是建議用ContentProvider

  • File
    即常說(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
  1. 存 (圖片舉例)
        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;
     }
 }
  1. 在當(dāng)前應(yīng)用程序中定義一個(gè)ContentProvider邪蛔。
<provider android:name=".MyProvider" android:authorities="com.test.MyProvider"/>
  1. 在當(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();
         }
     }
 }
  1. 其他應(yīng)用程序通過(guò)ContentResolver和Uri來(lái)獲取此ContentProvider的數(shù)據(jù)急黎。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市侧到,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌淤击,老刑警劉巖裁眯,帶你破解...
    沈念sama閱讀 206,723評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件布讹,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)争群,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,485評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)藏否,“玉大人鞭衩,你說(shuō)我怎么就攤上這事∩淙” “怎么了多柑?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,998評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)楣责。 經(jīng)常有香客問(wèn)我竣灌,道長(zhǎng),這世上最難降的妖魔是什么秆麸? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,323評(píng)論 1 279
  • 正文 為了忘掉前任初嘹,我火速辦了婚禮,結(jié)果婚禮上沮趣,老公的妹妹穿的比我還像新娘屯烦。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,355評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布驻龟。 她就那樣靜靜地躺著甸箱,像睡著了一般。 火紅的嫁衣襯著肌膚如雪迅脐。 梳的紋絲不亂的頭發(fā)上芍殖,一...
    開(kāi)封第一講書(shū)人閱讀 49,079評(píng)論 1 285
  • 那天,我揣著相機(jī)與錄音谴蔑,去河邊找鬼豌骏。 笑死,一個(gè)胖子當(dāng)著我的面吹牛隐锭,可吹牛的內(nèi)容都是我干的窃躲。 我是一名探鬼主播,決...
    沈念sama閱讀 38,389評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼钦睡,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼蒂窒!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起荞怒,我...
    開(kāi)封第一講書(shū)人閱讀 37,019評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤洒琢,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后褐桌,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體衰抑,經(jīng)...
    沈念sama閱讀 43,519評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,971評(píng)論 2 325
  • 正文 我和宋清朗相戀三年荧嵌,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了呛踊。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,100評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡啦撮,死狀恐怖谭网,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情赃春,我是刑警寧澤愉择,帶...
    沈念sama閱讀 33,738評(píng)論 4 324
  • 正文 年R本政府宣布,位于F島的核電站聘鳞,受9級(jí)特大地震影響薄辅,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜抠璃,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,293評(píng)論 3 307
  • 文/蒙蒙 一站楚、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧搏嗡,春花似錦窿春、人聲如沸拉一。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,289評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)蔚润。三九已至,卻和暖如春尺栖,著一層夾襖步出監(jiān)牢的瞬間嫡纠,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,517評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工延赌, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留除盏,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,547評(píng)論 2 354
  • 正文 我出身青樓挫以,卻偏偏與公主長(zhǎng)得像者蠕,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子掐松,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,834評(píng)論 2 345

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

  • 一.菜單Menu 1.OptionsMenu 選項(xiàng)菜單 也叫系統(tǒng)菜單,右上角的三點(diǎn) (1)高版本的菜單 ...
    chaohx閱讀 985評(píng)論 0 7
  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理踱侣,服務(wù)發(fā)現(xiàn),斷路器大磺,智...
    卡卡羅2017閱讀 134,600評(píng)論 18 139
  • 前幾天整理了Java面試題集合,今天再來(lái)整理下Android相關(guān)的面試題集合.如果你希望能得到最新的消息,可以關(guān)注...
    Boyko閱讀 3,621評(píng)論 8 135
  • 2017年5月17日 Kylin_Wu 標(biāo)注(★☆)為考綱明確給出考點(diǎn)(必考) 常見(jiàn)手機(jī)系統(tǒng)(★☆) And...
    Azur_wxj閱讀 1,801評(píng)論 0 10
  • 1. 今年暑假量没,大姨的兒子小濤向我咨詢文理選科的事玉转。這小子馬上要升高二了,學(xué)校要分文理科殴蹄。他是個(gè)對(duì)文史地非常著迷的...
    第四巫閱讀 543評(píng)論 5 3