Android操作配置文件封装类,使用json序列化的方式实现

简介: Android操作配置文件封装类,使用json序列化的方式实现

保存应用的一些配置信息是很常用的功能。


SharedPreferences是Android平台上一个轻量级的存储类,用来保存应用的一些常用配置,好用且强大,但是某些情况下不是很好用。


比如只支持JAVA基本数据类型,不支持自定义的数据类型。以XML文件的形式保存在 /data/data/PACKAGE_NAME/shared_prefs目录下,应用一旦卸载就跟着卸载了,没法保留配置或者把配置文件拷贝出来。(这在一些智能终端设备上保留配置信息和能够拷贝出来是常用的功能需求。)


虽然改变存储位置为其他目录,可以通过反射的方式实现,但是感觉还是不够简单。


之前有对SharedPreferences的一个操作封装,参见:https://blog.csdn.net/yyz_1987/article/details/104122764


所以,这里以json序列化存储文件的方式简单实现了一个,使用也更简单。


github地址;https://github.com/yangyongzhen/configer.git


举例,想保存个服务的IP和端口信息,使用如下:


SysCfg sysCfg = SysCfg.getInstance();
sysCfg.setIP("127.0.0.1");
sysCfg.setPort(5050);
sysCfg.save()


就这么简单,你已经完成了IP和Port的参数配置,sysCfg 是全局的一个系统参数配置类。(save操作会在内部存储为了一个名称为SysCfg的json文件)。


只需要应用启动时,如下调用,即完成的加载参数从文件到sysCfg反序列化过程:


SysCfg sysCfg = SysCfg.getInstance();
//从文件中加载json配置信息到sysCfg
sysCfg.load();


够简单吧,即使完全不了解SharedPreferences的人也能照葫芦画瓢的顺溜的使用。


比起操作SharedPreferences和sqllite的方式简单多了,而且可以更改存储位置和拷贝出配置文件。


SysCfg 配置文件类里,可以支持定义任何自定义类型,只要它能正常序列化为json都可以存储。


并不是你的配置文件类必须为SysCfg,这里仅是举例。定义成任意名称都可,只需集成自我封装的Configer基础类即可。


How to use?


Add it in your root build.gradle at the end of repositories:
  allprojects {
    repositories {
      ...
      maven { url 'https://jitpack.io' }
    }
  }
Step 2. Add the dependency
  dependencies {
          implementation 'com.github.yangyongzhen:configer:v1.0'
  }


完整示例如下:


package com.yangyongzhen.demo;
import com.yangyongzhen.configer.Configer;
import com.yangyongzhen.configer.Ignore;
/**
SysCfg 系统配置类
*/
public class SysCfg extends Configer {
    //Ignore,不序列化存储的使用Ignore注解
    @Ignore
    public static final String TAG = SysCfg.class.getSimpleName(); //做为配置文件的默认文件名
    @Ignore
    private static SysCfg _instance = null;
    private Integer Ver = 0;        //版本号
    private String Time ="";    //时间
    private String PosCode = ""; //终端编号
    private String UserName = "";   //登录用户名
    private String UserPwd = "";      //密码
    public SysCfg() {
        super(TAG);
    }
    private SysCfg(String filename) {
        super(filename);
    }
    public Integer getVer() {
        return Ver;
    }
    public void setVer(Integer ver) {
        Ver = ver;
    }
    public String getTime() {
        return Time;
    }
    public void setTime(String time) {
        Time = time;
    }
    public String getPosCode() {
        return PosCode;
    }
    public void setPosCode(String posCode) {
        PosCode = posCode;
    }
    public String getUserName() {
        return UserName;
    }
    public void setUserName(String userName) {
        UserName = userName;
    }
    public String getUserPwd() {
        return UserPwd;
    }
    public void setUserPwd(String userPwd) {
        UserPwd = userPwd;
    }
    @Override
    public String toString() {
        return "SysCfg{" +
                "Ver=" + Ver +
                ", Time='" + Time + '\'' +
                ", PosCode='" + PosCode + '\'' +
                ", UserName='" + UserName + '\'' +
                ", UserPwd='" + UserPwd + '\'' +
                '}';
    }
    public static SysCfg getInstance() {
        if (_instance == null) {
            synchronized(SysCfg.class){
                if (_instance == null) {
                    _instance = new SysCfg(TAG);
                }
            }
        }
        return _instance;
    }
}


package com.yangyongzhen.demo;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import com.yangyongzhen.configer.Configer;
public class MainActivity extends AppCompatActivity {
    private final String TAG = "MainActivity";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //更改存储目录为mydir,默认为/Android/data
        Configer.setDirPath("/mydir");
        SysCfg config = SysCfg.getInstance();
        //加载
        config.load();
        Log.d(TAG,config.toString());
        //赋值
        config.setVer(500);
        config.setUserName("yangyongzhen");
        //存储
        config.save();
        //再次读取测试
        SysCfg config1 = SysCfg.getInstance();
        config1.load();
        Log.d(TAG,config1.toString());
    }
}


贴一下基类的实现:


package com.yangyongzhen.configer;
import android.os.Environment;
import android.text.TextUtils;
import android.util.Log;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.yangyongzhen.configer.utils.FileUtil;
import com.yangyongzhen.configer.utils.GsonUtil;
import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
public class Configer{
    private static final String TAG = "Configer";
    private static String rootPath = Environment.getExternalStorageDirectory().getAbsolutePath();
    private static String dirPath = "/Android/data";
    private transient String filename;
    public Configer(String filename) {
        this.filename = filename;
    }
    public Boolean save(){
        //Log.d(TAG,this.toString());
        String jsStr = GsonUtil.GsonString(this);
        //Log.d(TAG,jsStr);
        Boolean ret = FileUtil.writeFile(rootPath+dirPath,filename,jsStr);
        return ret;
    }
    public Boolean load(){
        Class<?> cls = this.getClass();
        Object rec = null;
        String strfile = FileUtil.readFile(rootPath+dirPath+"/"+filename,"");
        if (!TextUtils.isEmpty(strfile)) {
            JSONObject jsonObject = JSON.parseObject(strfile);
            rec = GsonUtil.deserializer(jsonObject, this.getClass());
            Log.d(TAG,rec.toString());
        }
        if(rec != null){
            Class<?> cls1 = rec.getClass();
            Field[] declaredFields = cls.getDeclaredFields();
            for (int i = 0; i < declaredFields.length; i++) {
                Field field = declaredFields[i];
                if (field.isAnnotationPresent(Ignore.class)) {
                    continue;
                }
                try {
                    Method method = cls1.getDeclaredMethod("get"+upperHeadChar(field.getName()));
                    Object obj = method.invoke(rec);
                    field.setAccessible(true);
                    field.set(this,obj);
                } catch (Exception e) {
                    Log.d(TAG,e.toString());
                    //e.printStackTrace();
                    return false;
                }
            }
            return true;
        }
        return false;
    }
    /**
     * 首字母大写,in:deleteDate,out:DeleteDate
     */
    public static String upperHeadChar(String in) {
        String head = in.substring(0, 1);
        String out = head.toUpperCase() + in.substring(1, in.length());
        return out;
    }
    public static String getRootPath() {
        return rootPath;
    }
    public static void setRootPath(String rootPath) {
        Configer.rootPath = rootPath;
    }
    public static String getDirPath() {
        return dirPath;
    }
    public static void setDirPath(String dirPath) {
        Configer.dirPath = dirPath;
    }
}


相关文章
|
22天前
|
前端开发 数据可视化 Java
Android用Canvas画一个折线图,并加以简单封装
本文介绍了如何用Java绘制动态折线图,从固定折线图的实现到封装成可复用的组件。首先通过绘制XY坐标轴、添加坐标标签和绘制折线及数据点完成基础折线图。接着,将静态数据替换为动态输入,支持自定义X轴、Y轴和折线数据。代码中包含关键方法如`drawDaxes`(绘制坐标轴)、`drawAxispoint`(绘制坐标点)和`drawbrokenLine`(绘制折线)。最终实现可根据传入数据动态生成折线图,适用于Android开发中的数据可视化场景。
|
3月前
|
JSON Java 数据格式
微服务——SpringBoot使用归纳——Spring Boot返回Json数据及数据封装——封装统一返回的数据结构
本文介绍了在Spring Boot中封装统一返回的数据结构的方法。通过定义一个泛型类`JsonResult&lt;T&gt;`,包含数据、状态码和提示信息三个属性,满足不同场景下的JSON返回需求。例如,无数据返回时可设置默认状态码&quot;0&quot;和消息&quot;操作成功!&quot;,有数据返回时也可自定义状态码和消息。同时,文章展示了如何在Controller中使用该结构,通过具体示例(如用户信息、列表和Map)说明其灵活性与便捷性。最后总结了Spring Boot中JSON数据返回的配置与实际项目中的应用技巧。
194 0
|
24天前
|
JSON JavaScript 前端开发
Go语言JSON 序列化与反序列化 -《Go语言实战指南》
本文介绍了 Go 语言中使用 `encoding/json` 包实现 JSON 与数据结构之间的转换。内容涵盖序列化(`Marshal`)和反序列化(`Unmarshal`),包括基本示例、结构体字段标签的使用、控制字段行为的标签(如 `omitempty` 和 `-`)、处理 `map` 和切片、嵌套结构体序列化、反序列化未知结构(使用 `map[string]interface{}`)以及 JSON 数组的解析。最后通过表格总结了序列化与反序列化的方法及类型要求,帮助开发者快速掌握 JSON 数据处理技巧。
|
9月前
|
XML 存储 JSON
Twaver-HTML5基础学习(19)数据容器(2)_数据序列化_XML、Json
本文介绍了Twaver HTML5中的数据序列化,包括XML和JSON格式的序列化与反序列化方法。文章通过示例代码展示了如何将DataBox中的数据序列化为XML和JSON字符串,以及如何从这些字符串中反序列化数据,重建DataBox中的对象。此外,还提到了用户自定义属性的序列化注册方法。
107 1
|
10月前
|
JavaScript 前端开发 编译器
10min代码快速熟悉Tsconfig.json配置文件
【8月更文挑战第16天】10min代码快速熟悉Tsconfig.json配置文件
277 2
|
5月前
|
JSON 小程序 UED
微信小程序 app.json 配置文件解析与应用
本文介绍了微信小程序中 `app.json` 配置文件的详细
889 12
|
7月前
|
JSON JavaScript 前端开发
Go语言中json序列化的一个小坑,建议多留意一下
在Go语言开发中,JSON因其简洁和广泛的兼容性而常用于数据交换,但其在处理数字类型时存在精度问题。本文探讨了JSON序列化的一些局限性,并介绍了两种替代方案:Go特有的gob二进制协议,以及msgpack,两者都能有效解决类型保持和性能优化的问题。
171 7
|
7月前
|
JSON 前端开发 JavaScript
聊聊 Go 语言中的 JSON 序列化与 js 前端交互类型失真问题
在Web开发中,后端与前端的数据交换常使用JSON格式,但JavaScript的数字类型仅能安全处理-2^53到2^53间的整数,超出此范围会导致精度丢失。本文通过Go语言的`encoding/json`包,介绍如何通过将大整数以字符串形式序列化和反序列化,有效解决这一问题,确保前后端数据交换的准确性。
152 4
|
7月前
|
JSON JavaScript Java
对比JSON和Hessian2的序列化格式
通过以上对比分析,希望能够帮助开发者在不同场景下选择最适合的序列化格式,提高系统的整体性能和可维护性。
241 3
|
7月前
|
JSON 数据格式 索引
Python中序列化/反序列化JSON格式的数据
【11月更文挑战第4天】本文介绍了 Python 中使用 `json` 模块进行序列化和反序列化的操作。序列化是指将 Python 对象(如字典、列表)转换为 JSON 字符串,主要使用 `json.dumps` 方法。示例包括基本的字典和列表序列化,以及自定义类的序列化。反序列化则是将 JSON 字符串转换回 Python 对象,使用 `json.loads` 方法。文中还提供了具体的代码示例,展示了如何处理不同类型的 Python 对象。
193 1