本例代碼以SharedPreferences為數據存取載體。
利用SharedPreferences存取一個數據,步驟如下:
[java]
SharedPreferences sharedPre = getSharedPreferences(name, mode);
存:
SharedPreferences.Editor editor = sharedPre.edit();
editor.put(key,value);
editor.commit();
取:
value = sharedPre.get(key,defaultValue);
觀察以上,存取的關鍵是規范好對<key,value>的操作。其中key為字符串為預先定義好的。如果有多組<key,value>,則為每組想好key的名稱也是一件挺糾結的事。
本文自動讀取的核心在於直接使用數據實體的屬性名做為key值,在存取時遍歷數據實例的屬性,使用反射類讀取屬性的名稱,對屬性值進行寫出或寫入。
首先,事先定義好可處理的存取數據類型如下:
[java]
public static final int CLZ_BYTE = 1;
public static final int CLZ_SHORT = 2;
public static final int CLZ_INTEGER = 3;
public static final int CLZ_LONG = 4;
public static final int CLZ_STRING = 5;
public static final int CLZ_BOOLEAN = 6;
public static final int CLZ_FLOAT = 7;
public static final int CLZ_DOUBLE = 8;
public static final Map<Class<?>, Integer> TYPES;
static {
TYPES = new HashMap<Class<?>, Integer>();
TYPES.put(byte.class, CLZ_BYTE);
TYPES.put(short.class, CLZ_SHORT);
TYPES.put(int.class, CLZ_INTEGER);
TYPES.put(long.class, CLZ_LONG);
TYPES.put(String.class, CLZ_STRING);
TYPES.put(boolean.class, CLZ_BOOLEAN);
TYPES.put(float.class, CLZ_FLOAT);
TYPES.put(double.class, CLZ_DOUBLE);
}
寫出:
[java]
private void doSave(GoodsBean bean) {
SharedPreferences sharedPre = getSharedPreferences(GoodsBean.class.getName(), Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPre.edit();
Class<? extends GoodsBean> clazz = bean.getClass();
Field[] arrFiled = clazz.getDeclaredFields();
try {
for (Field f : arrFiled) {
Log.d("ANDROID_LAB", "type[" + f.getType() + "] name[" + f.getName() + "]");
int type = TYPES.get(f.getType());
switch (type) {
case CLZ_BYTE:
case CLZ_SHORT:
case CLZ_INTEGER:
editor.putInt(f.getName(), f.getInt(bean));
break;
case CLZ_LONG:
editor.putLong(f.getName(), f.getLong(bean));
break;
case CLZ_STRING:
editor.putString(f.getName(), (String) f.get(bean));
break;
case CLZ_BOOLEAN:
editor.putBoolean(f.getName(), f.getBoolean(bean));
break;
case CLZ_FLOAT:
editor.putFloat(f.getName(), f.getFloat(bean));
break;
case CLZ_DOUBLE:
editor.putFloat(f.getName(), (float) f.getDouble(bean));
break;
}
}
editor.commit();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
讀入:
[java]
private GoodsBean doRead() {
SharedPreferences sharedPre = getSharedPreferences(GoodsBean.class.getName(), Context.MODE_PRIVATE);
GoodsBean bean = new GoodsBean();
Class<? extends GoodsBean> clazz = bean.getClass();
Field[] arrFiled = clazz.getDeclaredFields();
try {
for (Field f : arrFiled) {
int type = TYPES.get(f.getType());
switch (type) {
case CLZ_BYTE:
byte byteValue = (byte) sharedPre.getInt(f.getName(), 0);
f.set(bean, byteValue);
break;
case CLZ_SHORT:
short shortValue = (short) sharedPre.getInt(f.getName(), 0);
f.set(bean, shortValue);
break;
case CLZ_INTEGER:
int intValue = sharedPre.getInt(f.getName(), 0);
f.set(bean, intValue);
break;
case CLZ_LONG:
long longValue = sharedPre.getLong(f.getName(), 0L);
f.set(bean, longValue);
break;
case CLZ_STRING:
String str = sharedPre.getString(f.getName(), null);
f.set(bean, str);
break;
case CLZ_BOOLEAN:
boolean bool = sharedPre.getBoolean(f.getName(), false);
f.set(bean, bool);
break;
case CLZ_FLOAT:
float floatValue = sharedPre.getFloat(f.getName(), 0.0f);
f.set(bean, floatValue);
break;
case CLZ_DOUBLE:
double doubleValue = sharedPre.getFloat(f.getName(), 0.0f);
f.set(bean, doubleValue);
break;
}
}
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
return bean;
}
GoodsBean.java
[java]
package lab.sodino.autosave;
public class GoodsBean {
public String name;
public long time;
public int price;
public boolean isPaid;
/** 測試用。 */
public byte testByte;
/** 測試用。 */
public short testShort;
public float cicle;
public double testDouble;
public String toString() {
StringBuffer strBuffer = new StringBuffer();
strBuffer.append("name[" + name + "]\n");
strBuffer.append("time[" + time + "]\n");
strBuffer.append("price[" + price + "]\n");
strBuffer.append("isPaid[" + isPaid + "]\n");
strBuffer.append("cicle[" + cicle + "]\n");
strBuffer.append("testByte[" + testByte + "]\n");
strBuffer.append("testShort[" + testShort + "]\n");
strBuffer.append("testDouble[" + testDouble + "]\n");
return strBuffer.toString();
}
public static GoodsBean newInstance() {
GoodsBean bean = new GoodsBean();
bean.name = "AutoSave";
bean.time = 12345234252342l;
bean.price = 1024;
bean.isPaid = true;
bean.cicle = 2.356f;
bean.testByte = 8;
bean.testShort = 128;
bean.testDouble = 9856.2145d;
return bean;
}
}
註意事項如下:
1.由於 SharedPreferences默認僅支持int/long/boolean/string/float 5種數據類型的讀寫,所以有一些強制轉換的操作。由01.gif可看出對double的存取操作會導致數據失真。在實際編碼工作中應註意些現象。如下圖:
2.需要處理好初始默認值。
自動存取的優點:
1.避免給一大堆key起名字,減少糾結時間。
2.方便、高效。數據結構的改變不需要重新修改存取過程。
3.出混淆包後,所有的key值也隨著一起混淆瞭,在一定程度上保護瞭程序邏輯。見圖01.png
缺點:
1.自動存取會將定義的數據結構全部存或全部取。如果想增加一些不需要本地存儲的屬性,則需要另建新類繼承原有數據結構才得以實現。
有利有弊,但總的來說利遠大於弊。