SharePreference技巧之保存一個(gè)對(duì)象

在Android中我們經(jīng)常需要持久化保存數(shù)據(jù)呛哟,這時(shí)可以使用文件苞俘,SharePreference癣诱,以及SQLite等计维。如果我想保存一個(gè)對(duì)象呢?有些人會(huì)立馬想到用orm框架撕予,但是我可能不想依賴這個(gè)框架鲫惶。實(shí)際上如果數(shù)據(jù)量不大,用SharePreference可能會(huì)更適合实抡。我們完全可以自己實(shí)現(xiàn)一個(gè)SharePreference版的持久化保存對(duì)象的工具類剑按。

直接看代碼

public class SpUtils {

    private static final String DEFAULT_SP_NAME = "default_sp";

    public static <T> T getObject(Context context, Class<T> clazz) {
        String key = getKey(clazz);
        String json = getString(context, key, null);
        if (TextUtils.isEmpty(json)) {
            return null;
        }
        try {
            Gson gson = new Gson();
            return gson.fromJson(json, clazz);
        } catch (Exception e) {
            return null;
        }
    }

    public static void putObject(Context context, Object object) {
        String key = getKey(object.getClass());
        Gson gson = new Gson();
        String json = gson.toJson(object);
        putString(context, key, json);
    }
    
    public static void removeObject(Context context, Class<?> clazz){
        remove(context, getKey(clazz));
    }

    public static String getKey(Class<?> clazz) {
        return clazz.getName();
    }

    public static void remove(Context context, String key) {
        SharedPreferences sp = context.getSharedPreferences(DEFAULT_SP_NAME, Context.MODE_PRIVATE);
        SharedPreferences.Editor edit = sp.edit();
        edit.remove(key);
        edit.commit();
    }

    public static void putString(Context context, String key, String value) {
        SharedPreferences sp = context.getSharedPreferences(DEFAULT_SP_NAME, Context.MODE_PRIVATE);
        SharedPreferences.Editor edit = sp.edit();
        edit.putString(key, value);
        edit.commit();
    }

    public static String getString(Context context, String key, String defValue) {
        SharedPreferences sp = context.getSharedPreferences(DEFAULT_SP_NAME, Context.MODE_PRIVATE);
        return sp.getString(key, defValue);
    }

}
  • putObject()方法中,我們以對(duì)象的類名字作為key澜术,以對(duì)象的json字符串作為value保存到SharePreference中。
  • getObject()方法猬腰,我們先獲取類的名字鸟废,再將它作為key,然后從SharePreference中獲取對(duì)應(yīng)的字符串姑荷,然后通過Gson將json字符串轉(zhuǎn)化為對(duì)象盒延。

到目前為止,看起來還不錯(cuò)鼠冕,但是聰明的你可能會(huì)發(fā)現(xiàn)添寺,如果我要保存的類是一個(gè)泛型呢,比如List<Person>懈费,用上面的方法肯定時(shí)不行了计露,因?yàn)榉盒蜁?huì)被擦除,List<String>List<Person>都是同一個(gè)類憎乙。關(guān)于泛型擦除可參考:Java 的泛型擦除和運(yùn)行時(shí)泛型信息獲取票罐。

那么對(duì)于泛型該如何處理呢?

回顧用Gson解析泛型類時(shí)泞边,我們可能寫過類似下面的代碼:

String json = result;
Gson gson = new Gson();
Type type =  new TypeToken<List<Person>>() {/*注意這里有個(gè)大括號(hào)*/}.getType());
List<Person> list = gson.fromJson(json, type);

這里用TypeToken去獲取泛型的信息该押。

Ok,我們已經(jīng)有思路了

public class SpUtils {
    // 獲取一個(gè)泛型的對(duì)象
    public static <T> T getObject(Context context, Type type) {
        String key = getKey(type);
        String json = getString(context, key, null);
        if (TextUtils.isEmpty(json)) {
            return null;
        }
        try {
            Gson gson = new Gson();
            return gson.fromJson(json, type);
        } catch (Exception e) {
            return null;
        }
    }
    // 保存一個(gè)泛型的對(duì)象
    public static void putObject(Context context, Object object, Type type) {
        String key = getKey(type);
        Gson gson = new Gson();
        String json = gson.toJson(object);
        putString(context, key, json);
    }

    public static void removeObject(Context context, Type type) {
        remove(context, getKey(type));
    }

    public static String getKey(Type type) {
        return type.toString();
    }

}

  • getObject()方法中阵谚,使用Type參數(shù)代替原來的Class
  • putObject()方法中蚕礼,新增一個(gè)Type參數(shù)烟具,用來獲取SharePreference中的key。

使用也不難:

List<Person> list = new ArrayList<>();
Person p = new Person(20, "張三1");
list.add(p);

p = new Person(20, "張三2");
list.add(p);
// 保存一個(gè)泛型對(duì)象
SpUtils.putObject(context, list,
        new TypeToken<List<Person>>() { }.getType());

// 獲取一個(gè)泛型對(duì)象
List<Person> list2 = SpUtils.getObject(context,
        new TypeToken<List<Person>>() { }.getType());

完整代碼如下:

import android.content.Context;
import android.content.SharedPreferences;
import android.text.TextUtils;

import com.google.gson.Gson;

import java.lang.reflect.Type;

public class SpUtils {

    private static final String DEFAULT_SP_NAME = "default_sp";

    // 通過類名字去獲取一個(gè)對(duì)象
    public static <T> T getObject(Context context, Class<T> clazz) {
        String key = getKey(clazz);
        String json = getString(context, key, null);
        if (TextUtils.isEmpty(json)) {
            return null;
        }
        try {
            Gson gson = new Gson();
            return gson.fromJson(json, clazz);
        } catch (Exception e) {
            return null;
        }
    }

    // 通過Type去獲取一個(gè)泛型對(duì)象
    public static <T> T getObject(Context context, Type type) {
        String key = getKey(type);
        String json = getString(context, key, null);
        if (TextUtils.isEmpty(json)) {
            return null;
        }
        try {
            Gson gson = new Gson();
            return gson.fromJson(json, type);
        } catch (Exception e) {
            return null;
        }
    }

    /**
     * 保存一個(gè)對(duì)象奠蹬,object必須是普通類朝聋,而不是泛型,如果是泛型,請(qǐng)使用 {@link SpUtils#putObject(Context, Object, Type)}
     *
     * @param context
     * @param object
     */
    public static void putObject(Context context, Object object) {
        String key = getKey(object.getClass());
        Gson gson = new Gson();
        String json = gson.toJson(object);
        putString(context, key, json);
    }

    /**
     * 保存一個(gè)泛型對(duì)象
     *
     * @param context
     * @param object
     * @param type    如果你要保存 List<Person> 這個(gè)類, type應(yīng)該 傳入 new TypeToken<List<Person>>() {}.getType()
     */
    public static void putObject(Context context, Object object, Type type) {
        String key = getKey(type);
        Gson gson = new Gson();
        String json = gson.toJson(object);
        putString(context, key, json);
    }

    public static void removeObject(Context context, Class<?> clazz) {
        remove(context, getKey(clazz));
    }

    public static void removeObject(Context context, Type type) {
        remove(context, getKey(type));
    }
    
    public static String getKey(Class<?> clazz) {
        return clazz.getName();
    }

    public static String getKey(Type type) {
        return type.toString();
    }

    public static void remove(Context context, String key) {
        SharedPreferences sp = context.getSharedPreferences(DEFAULT_SP_NAME, Context.MODE_PRIVATE);
        SharedPreferences.Editor edit = sp.edit();
        edit.remove(key);
        edit.commit();
    }

    public static void putString(Context context, String key, String value) {
        SharedPreferences sp = context.getSharedPreferences(DEFAULT_SP_NAME, Context.MODE_PRIVATE);
        SharedPreferences.Editor edit = sp.edit();
        edit.putString(key, value);
        edit.commit();
    }

    public static String getString(Context context, String key, String defValue) {
        SharedPreferences sp = context.getSharedPreferences(DEFAULT_SP_NAME, Context.MODE_PRIVATE);
        return sp.getString(key, defValue);
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末罩润,一起剝皮案震驚了整個(gè)濱河市玖翅,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌割以,老刑警劉巖金度,帶你破解...
    沈念sama閱讀 207,113評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異严沥,居然都是意外死亡猜极,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,644評(píng)論 2 381
  • 文/潘曉璐 我一進(jìn)店門消玄,熙熙樓的掌柜王于貴愁眉苦臉地迎上來跟伏,“玉大人,你說我怎么就攤上這事翩瓜∈馨猓” “怎么了?”我有些...
    開封第一講書人閱讀 153,340評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵兔跌,是天一觀的道長勘高。 經(jīng)常有香客問我,道長坟桅,這世上最難降的妖魔是什么华望? 我笑而不...
    開封第一講書人閱讀 55,449評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮仅乓,結(jié)果婚禮上赖舟,老公的妹妹穿的比我還像新娘。我一直安慰自己夸楣,他們只是感情好宾抓,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,445評(píng)論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著豫喧,像睡著了一般洞慎。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上嘿棘,一...
    開封第一講書人閱讀 49,166評(píng)論 1 284
  • 那天劲腿,我揣著相機(jī)與錄音,去河邊找鬼鸟妙。 笑死焦人,一個(gè)胖子當(dāng)著我的面吹牛挥吵,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播花椭,決...
    沈念sama閱讀 38,442評(píng)論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼忽匈,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了矿辽?” 一聲冷哼從身側(cè)響起丹允,我...
    開封第一講書人閱讀 37,105評(píng)論 0 261
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎袋倔,沒想到半個(gè)月后雕蔽,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,601評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡宾娜,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,066評(píng)論 2 325
  • 正文 我和宋清朗相戀三年批狐,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片前塔。...
    茶點(diǎn)故事閱讀 38,161評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡嚣艇,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出华弓,到底是詐尸還是另有隱情食零,我是刑警寧澤,帶...
    沈念sama閱讀 33,792評(píng)論 4 323
  • 正文 年R本政府宣布寂屏,位于F島的核電站慌洪,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏凑保。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,351評(píng)論 3 307
  • 文/蒙蒙 一涌攻、第九天 我趴在偏房一處隱蔽的房頂上張望欧引。 院中可真熱鬧,春花似錦恳谎、人聲如沸芝此。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,352評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽婚苹。三九已至,卻和暖如春鸵膏,著一層夾襖步出監(jiān)牢的瞬間膊升,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,584評(píng)論 1 261
  • 我被黑心中介騙來泰國打工谭企, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留廓译,地道東北人评肆。 一個(gè)月前我還...
    沈念sama閱讀 45,618評(píng)論 2 355
  • 正文 我出身青樓,卻偏偏與公主長得像非区,于是被迫代替她去往敵國和親瓜挽。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,916評(píng)論 2 344

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

  • 整體Retrofit內(nèi)容如下: 1征绸、Retrofit解析1之前哨站——理解RESTful 2久橙、Retrofit解析...
    隔壁老李頭閱讀 4,559評(píng)論 2 12
  • 在經(jīng)過一次沒有準(zhǔn)備的面試后,發(fā)現(xiàn)自己雖然寫了兩年的android代碼管怠,基礎(chǔ)知識(shí)卻忘的差不多了淆衷。這是程序員的大忌,沒...
    猿來如癡閱讀 2,834評(píng)論 3 10
  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 171,524評(píng)論 25 707
  • 對(duì)象的創(chuàng)建與銷毀 Item 1: 使用static工廠方法排惨,而不是構(gòu)造函數(shù)創(chuàng)建對(duì)象:僅僅是創(chuàng)建對(duì)象的方法吭敢,并非Fa...
    孫小磊閱讀 1,963評(píng)論 0 3
  • 南京鹿驼,南京。被江流劃為南北的都城辕宏,被歷史寫成故事畜晰,被故事活出現(xiàn)實(shí)。 我羨慕著那些在這里安頓自己的人瑞筐,把生活印在石頭...
    關(guān)于叁件事閱讀 307評(píng)論 0 0