Android 擼一個快取工具類

丨大麥發表於2018-07-19

近兩週一直在忙公司的移動專案,所以沒怎麼有時間學習和總結寫部落格。謝謝一些關心我的朋友和讀者。

前言

在開發過程中,我們不可避免需要快取許許多多的資料。例如:使用者登陸後的資訊;使用者的狀態;一些瀏覽的歷史紀錄等等;這時候我們就會經常需要讀寫快取。

所以今天想通過安卓一個輕量級的儲存類SharedPreferences和通過Gson去實現一個單例的安卓快取工具類;這樣有利於幫助我們更好的提高開發效率。

正文

目錄結構介紹(可跳過):

Android 擼一個快取工具類

model

這裡的model存放了一個User類和Friend類,主要是用來舉例利用快取工具類直接存放物件:

User.class

public class User {
    public String name;
    public String password;
    public List<Friend> friends;

    public User(String name, String password, List<Friend> friends) {
        this.name = name;
        this.password = password;
        this.friends = friends;
    }

    public User(String name, String password) {
        this.name = name;
        this.password = password;
    }

    @Override
    public String toString() {
        if (friends!=null && friends.size()>0){

            return "UserInfo:name"+this.name+",password"+this.password+friends.toString();
        }else {
            return "UserInfo:name"+this.name+",password"+this.password;
        }
    }
}


複製程式碼

Friend.class

public class Friend {
    private String name;
    private String password;

    public Friend(String name, String password) {
        this.name = name;
        this.password = password;
    }

    @Override
    public String toString() {
        return "FriendInfo:name"+this.name+",password"+this.password;
    }
}

複製程式碼

Util

工具目錄下面放了兩個類,SharedPreferencesUtils主要通過SharedPreferences、Gson和泛型去封裝一些最基本的資料存取操作,主要包括:存取boolean型別,存取int型別,存取float型別,存取String型別,存取long型別和存取Object和List型別。

SharedPreferencesUtils

public class SharedPreferencesUtils {
    private SharedPreferences.Editor mEditor;
    private SharedPreferences mSharedPreferences;
    private final String TAG="SharedPreferencesUtils";

    public SharedPreferencesUtils(Context context){
        mSharedPreferences= context
                .getSharedPreferences(context.getApplicationContext().getPackageName()
                        , Context.MODE_PRIVATE);
        mEditor=mSharedPreferences.edit();
    }

    /**
     * 儲存boolean型別的資料
     * @param key
     * @param value
     */
    public void saveBoolean(String key,boolean value){
        mEditor.putBoolean(key,value).commit();
    }

    /**
     * 獲取boolean型別的資料
     * @param key
     * @param defValue
     * @return
     */
    public boolean getBoolean(String key,boolean defValue){
        return mSharedPreferences.getBoolean(key,defValue);
    }

    /**
     * 儲存int型別的資料
     * @param key
     * @param value
     */
    public void saveInt(String key,int value){
        mEditor.putInt(key,value).commit();
    }

    /**
     * 獲取int型別的資料
     * @param key
     * @param defValue
     * @return
     */
    public int getInt(String key,int defValue){
        return mSharedPreferences.getInt(key,defValue);
    }

    /**
     * 儲存float型別的資料
     * @param key
     * @param value
     */
    public void saveFloat(String key,float value){
        mEditor.putFloat(key,value).commit();
    }

    /**
     * 獲取float型別的資料
     * @param key
     * @param defValue
     * @return
     */
    public float getFloat(String key,float defValue){
        return mSharedPreferences.getFloat(key,defValue);
    }

    /**
     * 儲存String型別的資料
     * @param key
     * @param value
     */
    public void saveString(String key,String value){
        mEditor.putString(key,value).commit();
    }

    /**
     * 獲取String型別的資料
     * @param key
     * @param defValue
     * @return
     */
    public String getString(String key,String defValue){
        return mSharedPreferences.getString(key,defValue);
    }
    /**
     * 儲存long型別的資料
     * @param key
     * @param value
     */
    public void saveLong(String key,long value){
        mEditor.putLong(key,value).commit();
    }

    /**
     * 獲取long型別的資料
     * @param key
     * @param defValue
     * @return
     */
    public long getLong(String key,long defValue){
        return mSharedPreferences.getLong(key,defValue);
    }

    /**
     * 通過Gson轉換成json格式的String進行儲存物件
     * @param key
     * @param value
     */
    public void saveObject(String key,Object value){
        this.saveString(key,new Gson().toJson(value));
    }

    /**
     * 通過Gson去解析json格式,轉換回物件返回
     * 如果為空,則返回null
     * @param key
     * @param classType
     * @param <T>
     * @return
     */
    public <T> T getObject(String key,Class<T> classType){
        String objectInfo=getString(key,"");
        if (objectInfo!=null && !objectInfo.isEmpty()){
            T result=null;
            try{
                result = new Gson().fromJson(objectInfo,classType);
            }catch (Exception e){
                Log.d(TAG,e.toString());
            }
            return result;
        }else {
            return null;
        }
    }

    /**
     * 儲存物件列表
     * @param key
     * @param value
     * @param <T>
     */
    public <T> void saveList(String key,List<T> value){
        saveString(key,new Gson().toJson(value));
    }

    /**
     * 獲取物件列表,如果為空,則返回null
     * @param key
     * @param typeToken
     * @param <T>
     * @return
     */
    public <T> List<T> getList(String key,TypeToken<List<T>> typeToken){
        String objectInfo=getString(key,"");
        if (objectInfo!=null && !objectInfo.isEmpty()){
            List<T> result=null;
            try{
                result=new Gson().fromJson(objectInfo,typeToken.getType());
            }catch (Exception e){
                Log.d(TAG,e.toString());
            }
            return result;
        }else {
            return null;
        }
    }

    /**
     * 清除所有快取
     */
    public void clearAll(){
        mEditor.clear();
        mEditor.commit();
    }
}

複製程式碼

DataCacheUtil

這個工具類主要是通過獲取SharedPreferencesUtils的例項,去封裝也寫業務層的存取邏輯。

public class DataCacheUtil {

    private SharedPreferencesUtils mSharedPreferences;
    private static DataCacheUtil mInstance;

    /**
     * 通過單例模式例項化物件
     * @param context
     */
    private DataCacheUtil(Context context){
        mSharedPreferences=new SharedPreferencesUtils(context);
    }

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


    /**
     * 儲存單個使用者資料儲存
     * @param user
     */
    public void saveUser(User user){
        mSharedPreferences.saveObject("user_info",user);
    }

    /**
     * 獲取單個使用者資料
     * @return
     */
    public User getUser(){
        return mSharedPreferences.getObject("user_info",User.class);
    }


    /**
     * 儲存List<User>物件
     * @param users
     */
    public void saveUserList(List<User> users){
        mSharedPreferences.saveList("user_list_info",users);
    }

    /**
     * 獲取List<User>物件
     * @return
     */
    public List<User> getUserList(){
        return  mSharedPreferences.getList("user_list_info",new TypeToken<List<User>>(){});
    }

    /**
     * 儲存User物件,物件中包括List<Friend>列表
     * @return
     */
    public void saveUserWithFriend(User user){
        mSharedPreferences.saveObject("user_with_friend",user);
    }

    /**
     * 獲取User物件,物件中包括List<Friend>列表
     * @return
     */
    public User getUserWithFriend(){
        return mSharedPreferences.getObject("user_with_friend",User.class);
    }
}

複製程式碼

以上兩個類,我們會在下面的文章中詳細介紹它的設計和使用。

如何使用

首先我們介紹下如何使用上面的工具類。

第一步獲取DataCacheUtil單例

通過呼叫DataCacheUtil.getInstance(context)獲取一個DataCacheUtil的單例。

第二部呼叫對應的業務方法去存取資料

例如:

        //存取單個User物件
        User user=new User("DaMai","DaMai123456");
        DataCacheUtil.getInstance(getApplicationContext()).saveUser(user);
        Log.d("DaMai",DataCacheUtil.getInstance(getApplicationContext()).getUser().toString());
複製程式碼

在這裡,我們通過呼叫事先編寫的業務存取方法saveUsergetUser儲存和取出對應的單個User物件。

是不是很簡單???

設計思路

儲存物件和物件列表

儲存boolean、int、float、long、String型別的資料其實沒什麼好說的,SharedPreferences.Editor都已經提供了對應的api。我們只要呼叫對應的api即可。

這裡我們重點說一下我們在SharedPreferencesUtils中如何儲存物件和物件列表。

儲存物件和物件列表

這裡我主要通過利用Gson,去將我們要儲存的物件轉換成了json格式,然後通過呼叫saveString方法去儲存json資料格式的字串。

獲取物件和物件列表

同樣的,我們先通過getString方法去獲取到對應的json格式的物件資料,然後通過Gson的fromJson方法去將json格式的String轉換回物件或物件列表型別。

getObject為例:

  /**
     * 通過Gson去解析json格式,轉換回物件返回
     * 如果為空,則返回null
     * @param key
     * @param classType
     * @param <T>
     * @return
     */
    public <T> T getObject(String key,Class<T> classType){
        String objectInfo=getString(key,"");
        if (objectInfo!=null && !objectInfo.isEmpty()){
            T result=null;
            try{
                result = new Gson().fromJson(objectInfo,classType);
            }catch (Exception e){
                Log.d(TAG,e.toString());
            }
            return result;
        }else {
            return null;
        }
    }
複製程式碼

這裡我們將getObject設計成泛型方法。

第一步通過key取出json格式的字串資料。

第二步我們通過對字串判斷是否為null或者為空字元,如果為空字串則直接返回null。

第三步通過Gson的fromJson()方法傳入json格式的字串和類型別,並返回泛型。

物件列表也採用了同樣的設計思路,這裡不在贅述。

DataCacheUtil採用單例的模式


    /**
     * 通過單例模式例項化物件
     * @param context
     */
    private DataCacheUtil(Context context){
        mSharedPreferences=new SharedPreferencesUtils(context);
    }

    /**
     * 呼叫建構函式時,傳入context.getApplicationContext()
     * @param context
     * @return
     */
    public static DataCacheUtil getInstance(Context context){
        if (mInstance==null){
            synchronized (DataCacheUtil.class){
                if (mInstance==null){
                    mInstance=new DataCacheUtil(context.getApplicationContext());    //傳入context.getApplicationContext()
                }
            }
        }
        return mInstance;
    }

複製程式碼

由於我們DataCacheUtil可能會在應用全域性各個地方都使用DataCacheUtil工具類,所以我們在運用單例的過程中呼叫建構函式例項化SharedPreferencesUtils時,傳入的context是ApplicationContext,這樣做是因為防止Activity的context由於生命週期的原因,導致記憶體洩漏。

Demo展示

MainActivity.class

public class MainActivity extends AppCompatActivity{

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //存取單個User物件
        User user=new User("DaMai","DaMai123456");
        DataCacheUtil.getInstance(getApplicationContext()).saveUser(user);
        Log.d("DaMai",DataCacheUtil.getInstance(getApplicationContext()).getUser().name);

        List<User> userList=new ArrayList<>();
        for (int i=0;i<10;i++){
            User temUser=new User("DaMai"+i,"DaMaiPass"+i);
            userList.add(temUser);
        }

        DataCacheUtil.getInstance(getApplicationContext()).saveUserList(userList);
        List<User> users=DataCacheUtil.getInstance(this).getUserList();
        for (User item:userList){
            Log.d("DaMai",item.toString());
        }


        List<Friend> friends=new ArrayList<>();
        for (int i=0;i<10;i++){
            Friend temFriend=new Friend("DaMai friend"+i,"DaMaiFriendPass"+i);
            friends.add(temFriend);
        }
        User vicky=new User("vicky","vicky123456",friends);
        DataCacheUtil.getInstance(this).saveUserWithFriend(vicky);
        Log.d("DaMai",DataCacheUtil.getInstance(this).getUserWithFriend().toString());

    }

}


複製程式碼

輸出:

07-19 17:16:08.630 26628-26628/com.example.sharedpreferencesdemo D/DaMai: DaMai
07-19 17:16:08.637 26628-26628/com.example.sharedpreferencesdemo D/DaMai: UserInfo:nameDaMai0,passwordDaMaiPass0
07-19 17:16:08.637 26628-26628/com.example.sharedpreferencesdemo D/DaMai: UserInfo:nameDaMai1,passwordDaMaiPass1
07-19 17:16:08.638 26628-26628/com.example.sharedpreferencesdemo D/DaMai: UserInfo:nameDaMai2,passwordDaMaiPass2
07-19 17:16:08.638 26628-26628/com.example.sharedpreferencesdemo D/DaMai: UserInfo:nameDaMai3,passwordDaMaiPass3
07-19 17:16:08.638 26628-26628/com.example.sharedpreferencesdemo D/DaMai: UserInfo:nameDaMai4,passwordDaMaiPass4
07-19 17:16:08.638 26628-26628/com.example.sharedpreferencesdemo D/DaMai: UserInfo:nameDaMai5,passwordDaMaiPass5
07-19 17:16:08.638 26628-26628/com.example.sharedpreferencesdemo D/DaMai: UserInfo:nameDaMai6,passwordDaMaiPass6
07-19 17:16:08.638 26628-26628/com.example.sharedpreferencesdemo D/DaMai: UserInfo:nameDaMai7,passwordDaMaiPass7
07-19 17:16:08.638 26628-26628/com.example.sharedpreferencesdemo D/DaMai: UserInfo:nameDaMai8,passwordDaMaiPass8
07-19 17:16:08.638 26628-26628/com.example.sharedpreferencesdemo D/DaMai: UserInfo:nameDaMai9,passwordDaMaiPass9
07-19 17:16:08.643 26628-26628/com.example.sharedpreferencesdemo D/DaMai: UserInfo:namevicky,passwordvicky123456[FriendInfo:nameDaMai friend0,passwordDaMaiFriendPass0, FriendInfo:nameDaMai friend1,passwordDaMaiFriendPass1, FriendInfo:nameDaMai friend2,passwordDaMaiFriendPass2, FriendInfo:nameDaMai friend3,passwordDaMaiFriendPass3, FriendInfo:nameDaMai friend4,passwordDaMaiFriendPass4, FriendInfo:nameDaMai friend5,passwordDaMaiFriendPass5, FriendInfo:nameDaMai friend6,passwordDaMaiFriendPass6, FriendInfo:nameDaMai friend7,passwordDaMaiFriendPass7, FriendInfo:nameDaMai friend8,passwordDaMaiFriendPass8, FriendInfo:nameDaMai friend9,passwordDaMaiFriendPass9]

複製程式碼

覆盤:

1、運用Gson將物件轉成Json格式的字串進行儲存,並通過泛型和Gson將Json格式的資料轉成物件進行取出。

2、業務工具類由於在全域性中頻繁使用,採用了單例模式。並在例項化的過程中運用getApplicationContext()去初始化SharedPreferences,避免因為Activity的生命週期導致的記憶體洩露。

Demo Git地址:

快取工具類Git地址:https://github.com/VickyGit/DataChacheDemo

我是大麥,如果喜歡我的文章,請給我一顆小心心。

相關文章