diff --git a/libappbase/src/main/java/cc/winboll/studio/libappbase/models/libs1520000/BaseBean.java b/libappbase/src/main/java/cc/winboll/studio/libappbase/models/libs1520000/BaseBean.java new file mode 100644 index 0000000..29fea44 --- /dev/null +++ b/libappbase/src/main/java/cc/winboll/studio/libappbase/models/libs1520000/BaseBean.java @@ -0,0 +1,415 @@ +package cc.winboll.studio.libappbase.models.libs1520000; + +import android.content.Context; +import android.util.JsonReader; +import android.util.JsonWriter; +import cc.winboll.studio.libappbase.LogUtils; +import cc.winboll.studio.libappbase.UTF8FileUtils; +import java.io.File; +import java.io.IOException; +import java.io.StringReader; +import java.io.StringWriter; +import java.util.ArrayList; + +/** + * WinBoLL JSON 数据模型基类(抽象类) + * 定义 Json Bean 的核心规范:序列化/反序列化、文件持久化、列表处理等通用逻辑, + * 子类需实现抽象方法,完成自身字段JSON读写业务逻辑 + * @Author 豆包&ZhanGSKen + * @CreateTime 2026/05/19 22:33:00 + * @EditTime 2026/05/19 23:15:48 + * @param 泛型约束,限定子类必须继承自BaseBean + */ +public abstract class BaseBean { + + // ====================== 静态常量 ====================== + /** 日志输出标识TAG */ + public static final String TAG = "BaseBean"; + /** JSON存储Bean类名字段Key,用于类型校验 */ + static final String BEAN_NAME = "BeanName"; + + // ====================== 构造方法 ====================== + /** + * 无参空构造,满足反射实例化要求 + */ + public BaseBean() { + + } + + // ====================== 抽象方法 ====================== + /** + * 获取当前实体类全类名 + * @return 全限定类名字符串 + */ + public abstract String getName(); + + /** + * 从JSON读取器解析构建实体对象 + * @param jsonReader JSON读取流 + * @return 解析完成实体对象 + * @throws IOException IO读写异常 + */ + public abstract T readBeanFromJsonReader(final JsonReader jsonReader) throws IOException; + + // ====================== 路径获取相关 ====================== + /** + * 获取单个实体默认存储JSON文件路径 + * @param context 应用上下文 + * @return 文件绝对路径 + */ + public String getBeanJsonFilePath(final Context context) { + return context.getExternalFilesDir(TAG) + "/" + getName() + ".json"; + } + + /** + * 获取实体列表默认存储JSON文件路径 + * @param context 应用上下文 + * @return 文件绝对路径 + */ + public String getBeanListJsonFilePath(final Context context) { + return context.getExternalFilesDir(TAG) + "/" + getName() + "_List.json"; + } + + // ====================== JSON序列化基础方法 ====================== + /** + * 写入基础Bean标识字段至JSON + * @param jsonWriter JSON写入流 + * @throws IOException 写入异常 + */ + public void writeThisToJsonWriter(final JsonWriter jsonWriter) throws IOException { + jsonWriter.name(BEAN_NAME).value(getName()); + } + + /** + * 基类通用字段解析回调 + * @param jsonReader JSON读取流 + * @param name 字段名 + * @return 是否完成当前字段解析 + * @throws IOException 读取异常 + */ + public boolean initObjectsFromJsonReader(final JsonReader jsonReader, final String name) throws IOException { + return false; + } + + // ====================== 实体字符串序列化 ====================== + @Override + public String toString() { + LogUtils.d(TAG, "执行BaseBean实体转JSON字符串"); + final StringWriter stringWriter = new StringWriter(); + final JsonWriter jsonWriter = new JsonWriter(stringWriter); + jsonWriter.setIndent(" "); + try { + jsonWriter.beginObject(); + writeThisToJsonWriter(jsonWriter); + jsonWriter.endObject(); + return stringWriter.toString(); + } catch (final IOException e) { + LogUtils.d(TAG, "实体转JSON字符串异常", Thread.currentThread().getStackTrace()); + } + return ""; + } + + // ====================== 列表序列化工具 ====================== + /** + * Bean列表转为格式化JSON数组字符串 + * @param beanList 实体集合 + * @param 实体泛型 + * @return JSON字符串 + */ + public static String toStringByBeanList(final ArrayList beanList) { + LogUtils.d(TAG, "执行Bean列表序列化JSON操作"); + try { + final StringWriter stringWriter = new StringWriter(); + final JsonWriter jsonWriter = new JsonWriter(stringWriter); + jsonWriter.setIndent(" "); + jsonWriter.beginArray(); + for (int i = 0; i < beanList.size(); i++) { + jsonWriter.beginObject(); + beanList.get(i).writeThisToJsonWriter(jsonWriter); + jsonWriter.endObject(); + } + jsonWriter.endArray(); + jsonWriter.close(); + return stringWriter.toString(); + } catch (final IOException e) { + LogUtils.d(TAG, "列表序列化JSON异常", Thread.currentThread().getStackTrace()); + } + return ""; + } + + // ====================== JSON字符串解析实体 ====================== + /** + * JSON文本解析为单个实体对象 + * @param szBean JSON文本 + * @param clazz 实体Class字节码 + * @param 实体泛型 + * @return 解析完成实体 + * @throws IOException 解析IO异常 + */ + public static T parseStringToBean(final String szBean, final Class clazz) throws IOException { + LogUtils.d(TAG, "进入字符串解析实体方法,目标Class:" + clazz.getSimpleName()); + final StringReader stringReader = new StringReader(szBean); + final JsonReader jsonReader = new JsonReader(stringReader); + try { + final T beanTemp = clazz.newInstance(); + return beanTemp.readBeanFromJsonReader(jsonReader); + } catch (final InstantiationException e) { + LogUtils.d(TAG, "实体反射实例化失败(InstantiationException)", Thread.currentThread().getStackTrace()); + } catch (final IllegalAccessException e) { + LogUtils.d(TAG, "实体反射权限访问失败(IllegalAccessException)", Thread.currentThread().getStackTrace()); + } + return null; + } + + /** + * JSON数组文本解析填充实体列表 + * @param szBeanList JSON数组文本 + * @param beanList 目标存储集合 + * @param clazz 实体字节码 + * @param 实体泛型 + * @return 解析结果 + */ + public static boolean parseStringToBeanList(final String szBeanList, final ArrayList beanList, final Class clazz) { + LogUtils.d(TAG, "进入列表字符串解析方法"); + try { + if (beanList == null) { + beanList = new ArrayList(); + } else { + beanList.clear(); + } + final StringReader stringReader = new StringReader(szBeanList); + final JsonReader jsonReader = new JsonReader(stringReader); + jsonReader.beginArray(); + while (jsonReader.hasNext()) { + final T beanTemp = clazz.newInstance(); + final T bean = beanTemp.readBeanFromJsonReader(jsonReader); + if (bean != null) { + beanList.add(bean); + } + } + jsonReader.endArray(); + return true; + } catch (final InstantiationException e) { + LogUtils.d(TAG, "列表解析反射实例化异常", Thread.currentThread().getStackTrace()); + } catch (final IllegalAccessException e) { + LogUtils.d(TAG, "列表解析反射权限异常", Thread.currentThread().getStackTrace()); + } catch (final IOException e) { + LogUtils.d(TAG, "列表解析JSON读写异常", Thread.currentThread().getStackTrace()); + } + return false; + } + + // ====================== 文件加载实体 ====================== + /** + * 从默认路径加载单个实体 + * @param context 上下文 + * @param clazz 实体字节码 + * @param 实体泛型 + * @return 加载实体 + */ + public static T loadBean(final Context context, final Class clazz) { + LogUtils.d(TAG, "执行默认路径加载实体数据"); + try { + final T beanTemp = clazz.newInstance(); + return loadBeanFromFile(beanTemp.getBeanJsonFilePath(context), clazz); + } catch (final InstantiationException e) { + LogUtils.d(TAG, "加载实体反射实例化失败", Thread.currentThread().getStackTrace()); + } catch (final IllegalAccessException e) { + LogUtils.d(TAG, "加载实体反射权限失败", Thread.currentThread().getStackTrace()); + } + return null; + } + + /** + * 自定义文件路径加载单个实体 + * @param szFilePath 文件路径 + * @param clazz 实体字节码 + * @param 实体泛型 + * @return 实体对象 + */ + public static T loadBeanFromFile(final String szFilePath, final Class clazz) { + LogUtils.d(TAG, "指定路径加载实体,路径:" + szFilePath); + try { + final File file = new File(szFilePath); + if (file.exists()) { + final T beanTemp = clazz.newInstance(); + final String json = UTF8FileUtils.readStringFromFile(szFilePath); + return beanTemp.parseStringToBean(json, clazz); + } + } catch (final InstantiationException e) { + LogUtils.d(TAG, "文件加载实体反射实例化异常", Thread.currentThread().getStackTrace()); + } catch (final IllegalAccessException e) { + LogUtils.d(TAG, "文件加载实体反射权限异常", Thread.currentThread().getStackTrace()); + } catch (final IOException e) { + LogUtils.d(TAG, "文件读取JSON数据异常", Thread.currentThread().getStackTrace()); + } + return null; + } + + /** + * 默认路径加载实体列表 + * @param context 上下文 + * @param beanListDst 目标集合 + * @param clazz 实体字节码 + * @param 实体泛型 + * @return 加载结果 + */ + public static boolean loadBeanList(final Context context, final ArrayList beanListDst, final Class clazz) { + LogUtils.d(TAG, "默认路径加载实体列表数据"); + try { + final T beanTemp = clazz.newInstance(); + return loadBeanListFromFile(beanTemp.getBeanListJsonFilePath(context), beanListDst, clazz); + } catch (final InstantiationException e) { + LogUtils.d(TAG, "列表加载反射实例化异常", Thread.currentThread().getStackTrace()); + } catch (final IllegalAccessException e) { + LogUtils.d(TAG, "列表加载反射权限异常", Thread.currentThread().getStackTrace()); + } + return false; + } + + /** + * 自定义路径加载实体列表 + * @param szFilePath 文件路径 + * @param beanList 目标集合 + * @param clazz 实体字节码 + * @param 实体泛型 + * @return 加载结果 + */ + public static boolean loadBeanListFromFile(final String szFilePath, final ArrayList beanList, final Class clazz) { + LogUtils.d(TAG, "指定路径加载实体列表,路径:" + szFilePath); + try { + final File file = new File(szFilePath); + if (file.exists()) { + final String listJson = UTF8FileUtils.readStringFromFile(szFilePath); + return parseStringToBeanList(listJson, beanList, clazz); + } + } catch (final IOException e) { + LogUtils.d(TAG, "列表文件读取异常", Thread.currentThread().getStackTrace()); + } + return false; + } + + // ====================== 实体数据保存文件 ====================== + /** + * 默认路径保存单个实体 + * @param context 上下文 + * @param bean 待保存实体 + * @param 实体泛型 + * @return 保存结果 + */ + public static boolean saveBean(final Context context, final T bean) { + return saveBeanToFile(bean.getBeanJsonFilePath(context), bean); + } + + /** + * 自定义路径保存单个实体 + * @param szFilePath 保存路径 + * @param bean 待保存实体 + * @param 实体泛型 + * @return 保存结果 + */ + public static boolean saveBeanToFile(final String szFilePath, final T bean) { + LogUtils.d(TAG, "执行实体数据写入文件操作"); + try { + final String json = bean.toString(); + UTF8FileUtils.writeStringToFile(szFilePath, json); + return true; + } catch (final IOException e) { + LogUtils.d(TAG, "实体写入文件异常", Thread.currentThread().getStackTrace()); + } + return false; + } + + /** + * 默认路径保存实体列表 + * @param context 上下文 + * @param beanList 实体集合 + * @param clazz 实体字节码 + * @param 实体泛型 + * @return 保存结果 + */ + public static boolean saveBeanList(final Context context, final ArrayList beanList, final Class clazz) { + LogUtils.d(TAG, "默认路径保存实体列表数据"); + try { + final T beanTemp = clazz.newInstance(); + return saveBeanListToFile(beanTemp.getBeanListJsonFilePath(context), beanList); + } catch (final InstantiationException e) { + LogUtils.d(TAG, "列表保存反射实例化异常", Thread.currentThread().getStackTrace()); + } catch (final IllegalAccessException e) { + LogUtils.d(TAG, "列表保存反射权限异常", Thread.currentThread().getStackTrace()); + } + return false; + } + + /** + * 自定义路径保存实体列表 + * @param szFilePath 保存路径 + * @param beanList 实体集合 + * @param 实体泛型 + * @return 保存结果 + */ + public static boolean saveBeanListToFile(final String szFilePath, final ArrayList beanList) { + LogUtils.d(TAG, "指定路径保存实体列表数据"); + try { + final String json = toStringByBeanList(beanList); + UTF8FileUtils.writeStringToFile(szFilePath, json); + return true; + } catch (final IOException e) { + LogUtils.d(TAG, "列表数据写入文件异常", Thread.currentThread().getStackTrace()); + } + return false; + } + + // ====================== Bean类型一致性校验 ====================== + /** + * 校验本地JSON列表内实体类型是否统一 + * @param szFilePath 列表文件路径 + * @param clazz 目标校验实体Class + * @param 实体泛型 + * @return 校验结果信息 + */ + public static String checkIsTheSameBeanListAndFile(final String szFilePath, final Class clazz) { + final StringBuilder sbResult = new StringBuilder(); + final String szErrorInfo = "Check Is The Same Bean List And File Error : "; + try { + int sameCount = 0; + int totalCount = 0; + final T beanTemp = clazz.newInstance(); + final String targetBeanName = beanTemp.getName(); + final String listJson = UTF8FileUtils.readStringFromFile(szFilePath); + final StringReader stringReader = new StringReader(listJson); + final JsonReader jsonReader = new JsonReader(stringReader); + jsonReader.beginArray(); + while (jsonReader.hasNext()) { + totalCount++; + jsonReader.beginObject(); + while (jsonReader.hasNext()) { + final String name = jsonReader.nextName(); + if (BEAN_NAME.equals(name)) { + if (targetBeanName.equals(jsonReader.nextString())) { + sameCount++; + } + } else { + jsonReader.skipValue(); + } + } + jsonReader.endObject(); + } + jsonReader.endArray(); + if (sameCount != totalCount) { + sbResult.append("Total : ").append(totalCount).append(" Diff : ").append(totalCount - sameCount); + } + } catch (final InstantiationException e) { + sbResult.append(szErrorInfo).append(e); + LogUtils.d(TAG, "类型校验反射实例化异常", Thread.currentThread().getStackTrace()); + } catch (final IllegalAccessException e) { + sbResult.append(szErrorInfo).append(e); + LogUtils.d(TAG, "类型校验反射权限异常", Thread.currentThread().getStackTrace()); + } catch (final IOException e) { + sbResult.append(szErrorInfo).append(e); + LogUtils.d(TAG, "类型校验文件读取解析异常", Thread.currentThread().getStackTrace()); + } + return sbResult.toString(); + } +} +