Android的配置文件操作的完美封装(使用注解 反射让配置文件操作如此清晰和简单)
时间:2022-07-22
本文章向大家介绍Android的配置文件操作的完美封装(使用注解 反射让配置文件操作如此清晰和简单),主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
我本意就是想简化下配置参数的读取和存储。
原来的方式太繁琐了。
比如我存个 IP ,就得单独调 put("ip","127.0.0.1"), 开机时还得先 String ip = get("ip")去加载。
在Android项目应用中,经常会用到读取和保存配置文件。
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)
如果参数少还无所谓,如果需要用到的参数很多,且到处都是。这种用法岂不是太混乱,太繁琐?
如果参数很多,累死个人了,很容易漏了或忘了赋值导致参数没存储。且没有全局管理意识的人会到处使用。导致你甚至不知道到底存储了哪些东东,哪些是存储了,哪些是没存储的。只能费劲儿的找,搜索,CTRL+F...
而我想要的效果是,所有参数都在一个类文件里定义,看起来很直观。需要存储时只要调用save()方法即可。
理想的样子是这样的:
//跟系统参数相关的所有参数配置和存储
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的所有参数
}
}
这样的话,使用起来多么的清晰直观啊!
之前用了一个笨方法,也算是实现了。但是还是使用起来还是不够精简。
参见:https://blog.csdn.net/yyz_1987/article/details/81414274
接下来将用java的注解和反射机制重新实现。
可以看到实现后使用是多么的简单直观。开机后先load一次从配置文件加载到成员变量中。
后续随便使用和赋值。想要保存,直接调用save()即可。且跟配置相关的参数都在全局的一个SysCfg中,
还害怕漏了或找不到吗?按这样封装好后,即便不会Android存储的人,也会清爽使用。
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();
以下为注解加反射机制实现:
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;
}
}
package com.newcapec.b601.config;
import android.content.Context;
import java.util.Arrays;
public class DealCfg extends Configer {
public static final String TAG = "DealCfg"; //做为配置文件的文件名
private static DealCfg _instance = null;
public static final int MAX_DISCINFO = 25;
private DealCfg(Context cx, String name) {
super(cx,name);
discInfo = new DiscInfo[MAX_DISCINFO];
for(int i = 0;i < MAX_DISCINFO; i++){
discInfo[i] = new DiscInfo(cx,DiscInfo.TAG+i);
}
}
public class DiscInfo extends Configer{
public static final String TAG = "DiscInfo";
public DiscInfo(Context cx, String name) {
super(cx, name);
}
@Save("cardType")
public Integer cardType = 0;
@Save("cardStat")
public Integer cardStat = 0;
@Save("purseDisc")
public Integer purseDisc = 0;
@Save("audioBuf")
public String audioBuf = "";
@Save("disBuf")
public String disBuf = "";
@Override
public String toString() {
return "DiscInfo{" +
"cardType=" + cardType +
", cardStat=" + cardStat +
", purseDisc=" + purseDisc +
", audioBuf='" + audioBuf + ''' +
", disBuf='" + disBuf + ''' +
'}';
}
}
//========================================================
//版本
//(需要持久化存储的,加上Save注解即可)
@Save("ver")
public Integer ver = 0;
//时间
@Save("time")
public String time = "";
public Integer port1 = 1000;
@Save("discInfo")
public DiscInfo[] discInfo;
@Override
public int saveCfg() {
int ret = 0;
ret = super.saveCfg();
if(ret != 0){
return ret;
}
for(int i = 0;i < MAX_DISCINFO; i++){
ret = discInfo[i].saveCfg();
if(ret != 0){
return ret;
}
}
return ret;
}
@Override
public int openCfg() {
int ret;
ret = super.openCfg();
if(ret != 0){
return ret;
}
for(int i = 0;i < MAX_DISCINFO; i++){
ret = discInfo[i].openCfg();
if(ret != 0){
return ret;
}
}
return ret;
}
public static DealCfg getInstance(Context context) {
if (_instance == null) {
synchronized(DealCfg.class){
if (_instance == null) {
_instance = new DealCfg(context,TAG);
}
}
}
return _instance;
}
@Override
public String toString() {
return "DealCfg{" +
"ver=" + ver +
", time='" + time + ''' +
", port1=" + port1 +
", discInfo=" + Arrays.toString(discInfo) +
'}';
}
}
- 协议森林07 傀儡 (UDP协议)
- 【设计模式】—— 访问者模式Visitor
- JAVA EE Eclipse下配置Tomcat服务器
- CentOS6.5菜鸟之旅:文件权限详解
- CMD魔法堂:支持显示UTF8编码的中文
- 【设计模式】—— 模板方法Template
- 【设计模式】—— 策略模式Strategy
- MyBatis魔法堂:即学即用篇
- 【设计模式】—— 状态模式State
- php环境无法上传文件的解决方法
- Java魔法堂:JUnit4使用详解
- Windows魔法堂:解决“由于启动计算机时出现页面文件配置问题.......”
- Java魔法堂:自定义和解析注解
- 【Hibernate那点事儿】—— Hibernate应该了解的知识
- java教程
- Java快速入门
- Java 开发环境配置
- Java基本语法
- Java 对象和类
- Java 基本数据类型
- Java 变量类型
- Java 修饰符
- Java 运算符
- Java 循环结构
- Java 分支结构
- Java Number类
- Java Character类
- Java String类
- Java StringBuffer和StringBuilder类
- Java 数组
- Java 日期时间
- Java 正则表达式
- Java 方法
- Java 流(Stream)、文件(File)和IO
- Java 异常处理
- Java 继承
- Java 重写(Override)与重载(Overload)
- Java 多态
- Java 抽象类
- Java 封装
- Java 接口
- Java 包(package)
- Java 数据结构
- Java 集合框架
- Java 泛型
- Java 序列化
- Java 网络编程
- Java 发送邮件
- Java 多线程编程
- Java Applet基础
- Java 文档注释
- Python3 多线程问题:ModuleNotFoundError: No module named 'thread',原因及解决办法。
- 文件传输和秒传
- 关于数据库的各种备份与还原姿势详解
- Python 技术篇-多线程的2种创建方法,多线程的简单用法,快速上手。
- Python 技术篇-调用浏览器访问指定网页,一行代码实现。非Selenium。
- 数据库热备份神器 - XtraBackup
- Python 技术篇-读取文件,将内容保存dict字典中。去掉字符串中的指定字符方法。dict字典的遍历。
- PyQt5 技术篇-plainTextEdit控件获得文本内容方法、设置文本内容方法。
- PyQt5 技术篇-鼠标移动控件显示提示,Qt Designer控件提示设置方法。
- PyQt5 技术篇-窗口名、窗口图标的设置方法。
- 101个shell脚本
- PyQt5 图片兼容性问题:"libpng warning: bKGD: invalid.",原因及解决办法。
- 编程语言经典小例题—Python版【持续更新】
- Python+selenium 自动化-切换窗口页签、切换iframe框架。确定页面是否包含iframe方法。
- JavaScript 技术篇-js获取iframe内的元素方法。