Android中虽然提供了SharedPreference类方便的对配置文件进行操作。但是好用吗?
假如有成百上千的参数需要存储,这样一个个分散的写法累死个人啊。本来几分钟能搞定的活,你可能得几个钟头。效率能是一个等级?且到处分散的写法,也容易让人看晕,给维护造成困难。
先来看结果:
原来的使用方式是这样的:
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(context);
//读取存储的IP和端口
String ip = sp.getInt("IP", "127.0.0.1");
int port = sp.getString("PORT",5050);
//保存IP和端口
ip = "218.28.111.121";
sp.putString("IP",ip)
如果参数少还无所谓,如果需要用到的参数很多,且到处都是。这种用法岂不是太混乱,太繁琐?
来看看原来的这种有多恐怖,
再来出一道题,假如我有一套票价参数要存储,每种卡类型有卡类型,折扣,提示信息等参数需要存储。让你用SharedPreferences去存储,你会怎么做?
先看下c语言里结构体票价参数的定义,让用Android的SharedPreferences怎么办?
即便不使用SharedPreferences,使用文件的方式存为json或xml或ini或yaml,哪个都不是那么简单好用。
如果参数很多,累死个人了,很容易漏了或忘了赋值导致参数没存储。且没有全局管理意识的人会到处使用。导致你甚至不知道到底存储了哪些东东,哪些是存储了,哪些是没存储的。只能费劲儿的找,搜索,CTRL+F...
再来看看这种方式:
syscfg.ip = "218.28.133.181";
syscfg.port = 22288;
syscfg.saveCfg();
Log.d(TAG,syscfg.toString());
dealCfg.ver = 12;
dealCfg.time = "201910251551";
dealCfg.discInfo[0].cardType = 5;
dealCfg.discInfo[0].purseDisc = 100;
dealCfg.discInfo[1].cardType = 6;
dealCfg.discInfo[1].purseDisc = 200;
dealCfg.saveCfg();
可以看到实现后使用是多么的简单直观。开机后先load一次从配置文件加载到成员变量中。
后续随便使用和赋值。想要保存,直接调用save()即可。且跟配置相关的参数都在全局的一个SysCfg中,
还害怕漏了或找不到吗?按这样封装好后,即便不会Android存储的人,也会清爽使用。
//跟系统参数相关的所有参数配置和存储
Class SysCfg{
String ip;
int port;
void load(){
...
}
void save(){
//自动把ip,port的内容存储起来
for(...){
put("ip",value)
...
}
static void main(String[] args){
SysCfg cfg = new SysCfg();
cfg.load()//加载配置文件中的参数到成员变量中
cfg.ip = "127.0.0.1"; //赋值
cfg.port= 5050;
cfg.save();//自动持久化存储了SysCfg的所有参数
}
}
最后,封装实现的代码分享一下,使用注解+反射让配置文件操作如此清晰和简单。
所有需要用到的参数,定义在一个继承自Configer的类中即可。
package com.newcapec.b601.config;
import android.content.Context;
import java.lang.reflect.Field;
/**
* Android存储的封装
* Author:yangyongzhen
* QQ:534117529
*/
public class Configer {
public static final String TAG = "Configer"; //做为配置文件的文件名
private SharedPreferencesHelper helper;
//===========================================================
public Configer(Context cx,String name){
helper = new SharedPreferencesHelper(cx,name);
}
/**
* 自动完成所有带有Save注解的成员变量的存储
*/
public int saveCfg(){
Class cls = this.getClass();
Field[] fields = cls.getDeclaredFields();
for(Field field :fields) {
if (field.isAnnotationPresent(Save.class)) {
try {
Save sa = (Save) field.getAnnotation(Save.class);
String key = sa.value();
String val = (String) helper.get(key,"");
Object obj = field.get(this);
if(obj.equals(val)){
continue;
}
if(obj instanceof String) {
helper.put(key,obj);
}else if(obj instanceof Integer){
helper.put(key,obj);
}
} catch (IllegalAccessException e) {
e.printStackTrace();
return 1;
}
}
}
return 0;
}
/**
* 自动完成所有带有Save注解的成员变量的加载
* @return
*/
public int openCfg(){
Class cls = this.getClass();
Field[] fields = cls.getDeclaredFields();
for(Field field :fields) {
if (field.isAnnotationPresent(Save.class)) {
try {
Save sa = (Save) field.getAnnotation(Save.class);
String key = sa.value();
if(field.get(this) instanceof String) {
String val = (String) helper.get(key,"");
field.set(this,val);
}else if(field.get(this) instanceof Integer){
Integer val = (Integer) helper.get(key,0);
field.set(this,val);
}
} catch (IllegalAccessException e) {
e.printStackTrace();
return 1;
}
}
}
return 0;
}
}
Save的注解也很简单:
package com.newcapec.testsqllite.config;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
@Target(value = {ElementType.FIELD})
@Retention(value = RetentionPolicy.RUNTIME)
public @interface Save {
String value();
}
使用方式:
package com.newcapec.b601.config;
import android.content.Context;
public class SysCfg extends Configer {
public static final String TAG = "SysCfg"; //做为配置文件的文件名
private static SysCfg _instance = null;
private SysCfg(Context cx,String name) {
super(cx,name);
}
//========================================================
//IP地址
//(需要持久化存储的,加上Save注解即可)
@Save("ip")
public String ip = "127.0.0.1";
//服务器端口
@Save("port")
public Integer port = 999;
public Integer port1 = 1000;
@Override
public String toString() {
return "Sys{" +
"ip='" + ip + '\'' +
", port=" + port +
", port1=" + port1 +
'}';
}
public static SysCfg getInstance(Context context) {
if (_instance == null) {
synchronized(SysCfg.class){
if (_instance == null) {
_instance = new SysCfg(context,TAG);
}
}
}
return _instance;
}
}
syscfg.ip = "218.28.133.181";
syscfg.port = 22288;
syscfg.saveCfg();
Log.d(TAG,syscfg.toString());
dealCfg.ver = 12;
dealCfg.time = "201910251551";
dealCfg.discInfo[0].cardType = 5;
dealCfg.discInfo[0].purseDisc = 100;
dealCfg.discInfo[1].cardType = 6;
dealCfg.discInfo[1].purseDisc = 200;
dealCfg.saveCfg();