Android的配置文件操作的完美封装(使用注解 反射让配置文件操作如此清晰和简单)

简介: 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) +
                '}';
    }
}
相关文章
|
6月前
|
Java 数据库 Android开发
【专栏】Kotlin在Android开发中的多线程优化,包括线程池、协程的使用,任务分解、避免阻塞操作以及资源管理
【4月更文挑战第27天】本文探讨了Kotlin在Android开发中的多线程优化,包括线程池、协程的使用,任务分解、避免阻塞操作以及资源管理。通过案例分析展示了网络请求、图像处理和数据库操作的优化实践。同时,文章指出并发编程的挑战,如性能评估、调试及兼容性问题,并强调了多线程优化对提升应用性能的重要性。开发者应持续学习和探索新的优化策略,以适应移动应用市场的竞争需求。
160 5
|
6月前
|
Java Android开发
Android系统 获取用户最后操作时间回调实现和原理分析
Android系统 获取用户最后操作时间回调实现和原理分析
187 0
|
6月前
|
Linux Android开发
测试程序之提供ioctl函数应用操作GPIO适用于Linux/Android
测试程序之提供ioctl函数应用操作GPIO适用于Linux/Android
116 0
|
6月前
|
Android开发
Android 分享机顶盒项目的封装类《GridView》(二)(转)
Android 分享机顶盒项目的封装类《GridView》(二)(转)
48 2
|
3月前
|
Java 测试技术 Android开发
Android项目架构设计问题之使用反射调用类的私有方法如何解决
Android项目架构设计问题之使用反射调用类的私有方法如何解决
29 0
|
3月前
|
Android开发 iOS开发
Android项目架构设计问题之将隐式跳转的逻辑进行抽象和封装如何解决
Android项目架构设计问题之将隐式跳转的逻辑进行抽象和封装如何解决
41 0
|
3月前
|
编解码 API 开发工具
Android平台轻量级RTSP服务模块二次封装版调用说明
本文介绍了Android平台上轻量级RTSP服务模块的二次封装实践,旨在简化开发流程,让开发者能更专注于业务逻辑。通过`LibPublisherWrapper`类提供的API,可在应用中轻松初始化RTSP服务、配置视频参数(如分辨率、编码类型)、启动与停止RTSP服务及流发布,并获取RTSP会话数量。此外,还展示了如何处理音频和视频数据的采集与推送。最后,文章提供了从启动服务到销毁资源的完整示例,帮助开发者快速集成实时流媒体功能。
|
5月前
|
XML API 开发工具
Android Bitmap 加载与像素操作
Android Bitmap 加载与像素操作
48 2
|
4月前
|
Android开发
Android kernel 操作gpio
Android kernel 操作gpio
42 0
|
5月前
|
存储 算法 Java
Android 进阶——代码插桩必知必会&ASM7字节码操作
Android 进阶——代码插桩必知必会&ASM7字节码操作
241 0