近兩週一直在忙公司的移動專案,所以沒怎麼有時間學習和總結寫部落格。謝謝一些關心我的朋友和讀者。
前言
在開發過程中,我們不可避免需要快取許許多多的資料。例如:使用者登陸後的資訊;使用者的狀態;一些瀏覽的歷史紀錄等等;這時候我們就會經常需要讀寫快取。
所以今天想通過安卓一個輕量級的儲存類SharedPreferences和通過Gson去實現一個單例的安卓快取工具類;這樣有利於幫助我們更好的提高開發效率。
正文
目錄結構介紹(可跳過):
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());
複製程式碼
在這裡,我們通過呼叫事先編寫的業務存取方法saveUser
和getUser
儲存和取出對應的單個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
我是大麥,如果喜歡我的文章,請給我一顆小心心。