From 7d872fd14c25f020bd973b98744520540ad4403d Mon Sep 17 00:00:00 2001 From: QingLong Date: Wed, 20 May 2026 04:00:01 +0800 Subject: [PATCH] =?UTF-8?q?=E5=90=88=E5=B9=B6=E6=A8=A1=E5=9D=97APPBase=20?= =?UTF-8?q?=E5=90=8C=E6=AD=A5=E6=9C=80=E6=96=B0=E6=97=B6=E9=97=B4=E6=A0=87?= =?UTF-8?q?=E7=AD=BEappbase-v15.20.18?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- appbase/build.properties | 8 +- .../java/cc/winboll/studio/appbase/App.java | 6 - .../studio/appbase/model/TestBean.java | 2 +- libappbase/build.properties | 8 +- .../winboll/studio/libappbase/APPModel.java | 1 + .../studio/libappbase/GlobalApplication.java | 11 +- .../studio/libappbase/LogActivity.java | 5 + .../winboll/studio/libappbase/LogUtils.java | 63 ++- .../studio/libappbase/LogUtilsBean.java | 1 + .../libappbase/LogUtilsClassTAGBean.java | 1 + .../studio/libappbase/LogViewThread.java | 51 ++- .../models/libs1520000/BaseBean.java | 415 ++++++++++++++++++ 12 files changed, 499 insertions(+), 73 deletions(-) create mode 100644 libappbase/src/main/java/cc/winboll/studio/libappbase/models/libs1520000/BaseBean.java diff --git a/appbase/build.properties b/appbase/build.properties index 5cc2d78..f4e7c81 100644 --- a/appbase/build.properties +++ b/appbase/build.properties @@ -1,8 +1,8 @@ #Created by .winboll/winboll_app_build.gradle -#Tue May 19 20:49:13 HKT 2026 -stageCount=18 +#Wed May 20 03:13:41 HKT 2026 +stageCount=19 libraryProject=libappbase baseVersion=15.20 -publishVersion=15.20.17 +publishVersion=15.20.18 buildCount=0 -baseBetaVersion=15.20.18 +baseBetaVersion=15.20.19 diff --git a/appbase/src/main/java/cc/winboll/studio/appbase/App.java b/appbase/src/main/java/cc/winboll/studio/appbase/App.java index 9df2ed8..9a19876 100644 --- a/appbase/src/main/java/cc/winboll/studio/appbase/App.java +++ b/appbase/src/main/java/cc/winboll/studio/appbase/App.java @@ -22,12 +22,6 @@ public class App extends GlobalApplication { @Override public void onCreate() { super.onCreate(); - // 如果应用不在调试状态,就根据编译类型设置调试状态 - if (isDebugging() != true) { - setIsDebugging(BuildConfig.DEBUG); - } - // release 版调试码 - //setIsDebugging(!BuildConfig.DEBUG); // 初始化 Toast 工具类(传入应用全局上下文,确保 Toast 可在任意地方调用) ToastUtils.init(getApplicationContext()); diff --git a/appbase/src/main/java/cc/winboll/studio/appbase/model/TestBean.java b/appbase/src/main/java/cc/winboll/studio/appbase/model/TestBean.java index ee3e70a..cb91442 100644 --- a/appbase/src/main/java/cc/winboll/studio/appbase/model/TestBean.java +++ b/appbase/src/main/java/cc/winboll/studio/appbase/model/TestBean.java @@ -2,8 +2,8 @@ package cc.winboll.studio.appbase.model; import android.util.JsonReader; import android.util.JsonWriter; -import cc.winboll.studio.libappbase.BaseBean; import cc.winboll.studio.libappbase.LogUtils; +import cc.winboll.studio.libappbase.models.libs1520000.BaseBean; import java.io.IOException; /** diff --git a/libappbase/build.properties b/libappbase/build.properties index 5cc2d78..f4e7c81 100644 --- a/libappbase/build.properties +++ b/libappbase/build.properties @@ -1,8 +1,8 @@ #Created by .winboll/winboll_app_build.gradle -#Tue May 19 20:49:13 HKT 2026 -stageCount=18 +#Wed May 20 03:13:41 HKT 2026 +stageCount=19 libraryProject=libappbase baseVersion=15.20 -publishVersion=15.20.17 +publishVersion=15.20.18 buildCount=0 -baseBetaVersion=15.20.18 +baseBetaVersion=15.20.19 diff --git a/libappbase/src/main/java/cc/winboll/studio/libappbase/APPModel.java b/libappbase/src/main/java/cc/winboll/studio/libappbase/APPModel.java index d4dc9ca..56c3c5c 100644 --- a/libappbase/src/main/java/cc/winboll/studio/libappbase/APPModel.java +++ b/libappbase/src/main/java/cc/winboll/studio/libappbase/APPModel.java @@ -2,6 +2,7 @@ package cc.winboll.studio.libappbase; import android.util.JsonReader; import android.util.JsonWriter; +import cc.winboll.studio.libappbase.models.libs1520000.BaseBean; import java.io.IOException; /** diff --git a/libappbase/src/main/java/cc/winboll/studio/libappbase/GlobalApplication.java b/libappbase/src/main/java/cc/winboll/studio/libappbase/GlobalApplication.java index 378ac59..e03ac72 100644 --- a/libappbase/src/main/java/cc/winboll/studio/libappbase/GlobalApplication.java +++ b/libappbase/src/main/java/cc/winboll/studio/libappbase/GlobalApplication.java @@ -129,11 +129,10 @@ public class GlobalApplication extends Application { // 初始化单例实例(确保在所有初始化操作前完成) sInstance = this; + restoreDebugStatus(); // 初始化基础组件(日志、崩溃处理、Toast) initCoreComponents(); - // 恢复/初始化调试模式状态(从本地文件读取,无文件则默认关闭调试) - restoreDebugStatus(); - // 新增:初始化服务器地址(从 SP 读取到内存,提高后续访问效率) + // 初始化服务器地址(从 SP 读取到内存,提高后续访问效率) initWinbollHost(); LogUtils.d(TAG, "GlobalApplication 初始化完成,单例实例已创建"); @@ -144,7 +143,11 @@ public class GlobalApplication extends Application { */ private void initCoreComponents() { // 初始化日志工具(传入 Application 上下文) - LogUtils.init(this); + + // 调试状态下初始化日志工具 + if (GlobalApplication.isDebugging()) { + LogUtils.init(this); + } // 初始化全局异常处理器(捕获应用崩溃信息,用于调试或上报) CrashHandler.init(this); // 初始化 Toast 工具(统一 Toast 样式、避免内存泄漏等) diff --git a/libappbase/src/main/java/cc/winboll/studio/libappbase/LogActivity.java b/libappbase/src/main/java/cc/winboll/studio/libappbase/LogActivity.java index 8c0e5af..1cc8f5c 100644 --- a/libappbase/src/main/java/cc/winboll/studio/libappbase/LogActivity.java +++ b/libappbase/src/main/java/cc/winboll/studio/libappbase/LogActivity.java @@ -27,6 +27,11 @@ public class LogActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + if(!GlobalApplication.isDebugging()) { + ToastUtils.show("非调试状态日志功能不可用"); + finish(); + } + // 设置布局文件(包含 LogView 控件) setContentView(R.layout.activity_log); diff --git a/libappbase/src/main/java/cc/winboll/studio/libappbase/LogUtils.java b/libappbase/src/main/java/cc/winboll/studio/libappbase/LogUtils.java index a0e4f2a..e2124da 100644 --- a/libappbase/src/main/java/cc/winboll/studio/libappbase/LogUtils.java +++ b/libappbase/src/main/java/cc/winboll/studio/libappbase/LogUtils.java @@ -67,45 +67,29 @@ public class LogUtils { // ====================== 初始化入口 ====================== public static void init(final Context context) { - init(context, LOG_LEVEL.Off); + init(context, LOG_LEVEL.Off); } public static void init(final Context context, final LOG_LEVEL logLevel) { - Log.d(TAG, "init 执行日志工具初始化"); - _mContext = context; + if (!GlobalApplication.isDebugging()) { + return; + } + Log.d(TAG, "init 执行日志工具初始化"); + _mContext = context; - if (GlobalApplication.isDebugging()) { - initDebugDir(); - } else { - initReleaseDir(); - } + initLogUtilsDir(); - initLogConfigBean(); - addClassTAGList(); - loadTAGBeanSettings(); - checkAndTrimLogFileSize(); + initLogConfigBean(); + addClassTAGList(); + loadTAGBeanSettings(); + checkAndTrimLogFileSize(); - _IsInited = true; - Log.d(TAG, "init 日志工具初始化完成"); + _IsInited = true; + Log.d(TAG, "init 执行日志工具初始化完成"); } // ====================== 目录初始化 ====================== - private static void initDebugDir() { - final Context appContext = _mContext.getApplicationContext(); - _mfLogCacheDir = new File(appContext.getExternalCacheDir(), TAG); - if (!_mfLogCacheDir.exists()) { - _mfLogCacheDir.mkdirs(); - } - _mfLogCatchFile = new File(_mfLogCacheDir, "log.txt"); - - _mfLogDataDir = appContext.getExternalFilesDir(TAG); - if (!_mfLogDataDir.exists()) { - _mfLogDataDir.mkdirs(); - } - _mfLogUtilsBeanFile = new File(_mfLogDataDir, TAG + ".json"); - } - - private static void initReleaseDir() { + private static void initLogUtilsDir() { final Context appContext = _mContext.getApplicationContext(); _mfLogCacheDir = new File(appContext.getCacheDir(), TAG); if (!_mfLogCacheDir.exists()) { @@ -113,7 +97,7 @@ public class LogUtils { } _mfLogCatchFile = new File(_mfLogCacheDir, "log.txt"); - _mfLogDataDir = new File(appContext.getFilesDir(), TAG); + _mfLogDataDir = appContext.getExternalFilesDir(TAG); if (!_mfLogDataDir.exists()) { _mfLogDataDir.mkdirs(); } @@ -136,7 +120,7 @@ public class LogUtils { } final long KEEP_FILE_SIZE = 25000L; // ~25KB 确保剪贴板可完整复制 - final long MAX_FILE_SIZE = 2*KEEP_FILE_SIZE; + final long MAX_FILE_SIZE = 2 * KEEP_FILE_SIZE; final long fileSize = _mfLogCatchFile.length(); if (fileSize <= MAX_FILE_SIZE) { @@ -266,6 +250,9 @@ public class LogUtils { } public static void setTAGListEnable(final String tag, final boolean isEnable) { + if (!_IsInited) { + return; + } final Iterator> iterator = mapTAGList.entrySet().iterator(); while (iterator.hasNext()) { final Map.Entry entry = iterator.next(); @@ -279,6 +266,9 @@ public class LogUtils { } public static void setALlTAGListEnable(final boolean isEnable) { + if (!_IsInited) { + return; + } for (final Map.Entry entry : mapTAGList.entrySet()) { entry.setValue(isEnable); } @@ -288,15 +278,22 @@ public class LogUtils { // ====================== 日志级别控制 ====================== public static void setLogLevel(final LOG_LEVEL logLevel) { + if (_mLogUtilsBean == null) { + Log.d(TAG, "setLogLevel LogUtils未初始化,忽略设置日志级别"); + return; + } _mLogUtilsBean.setLogLevel(logLevel); _mLogUtilsBean.saveBeanToFile(_mfLogUtilsBeanFile.getPath(), _mLogUtilsBean); } public static LOG_LEVEL getLogLevel() { - return _mLogUtilsBean.getLogLevel(); + return _mLogUtilsBean == null ?LOG_LEVEL.Off: _mLogUtilsBean.getLogLevel(); } private static boolean isLoggable(final String tag, final LOG_LEVEL logLevel) { + if (!GlobalApplication.isDebugging()) { + return false; + } if (!_IsInited) { return false; } diff --git a/libappbase/src/main/java/cc/winboll/studio/libappbase/LogUtilsBean.java b/libappbase/src/main/java/cc/winboll/studio/libappbase/LogUtilsBean.java index b8556b9..b237f41 100644 --- a/libappbase/src/main/java/cc/winboll/studio/libappbase/LogUtilsBean.java +++ b/libappbase/src/main/java/cc/winboll/studio/libappbase/LogUtilsBean.java @@ -2,6 +2,7 @@ package cc.winboll.studio.libappbase; import android.util.JsonReader; import android.util.JsonWriter; +import cc.winboll.studio.libappbase.models.libs1520000.BaseBean; import java.io.IOException; /** diff --git a/libappbase/src/main/java/cc/winboll/studio/libappbase/LogUtilsClassTAGBean.java b/libappbase/src/main/java/cc/winboll/studio/libappbase/LogUtilsClassTAGBean.java index 83ce79e..6e91314 100644 --- a/libappbase/src/main/java/cc/winboll/studio/libappbase/LogUtilsClassTAGBean.java +++ b/libappbase/src/main/java/cc/winboll/studio/libappbase/LogUtilsClassTAGBean.java @@ -2,6 +2,7 @@ package cc.winboll.studio.libappbase; import android.util.JsonReader; import android.util.JsonWriter; +import cc.winboll.studio.libappbase.models.libs1520000.BaseBean; import java.io.IOException; /** diff --git a/libappbase/src/main/java/cc/winboll/studio/libappbase/LogViewThread.java b/libappbase/src/main/java/cc/winboll/studio/libappbase/LogViewThread.java index 3941e45..2c4f805 100644 --- a/libappbase/src/main/java/cc/winboll/studio/libappbase/LogViewThread.java +++ b/libappbase/src/main/java/cc/winboll/studio/libappbase/LogViewThread.java @@ -1,6 +1,7 @@ package cc.winboll.studio.libappbase; import android.os.FileObserver; +import java.io.File; import java.lang.ref.WeakReference; /** @@ -51,30 +52,38 @@ public class LogViewThread extends Thread { */ @Override public void run() { - // 获取日志缓存目录路径(从 LogUtils 统一获取,确保路径一致性) - String logDirPath = LogUtils.getLogCacheDir().getPath(); - LogUtils.d(TAG, "启动日志文件监听,监听目录:" + logDirPath); + // 调试状态进行日志输出任务 + if (GlobalApplication.isDebugging()) { + // 获取日志缓存目录路径(从 LogUtils 统一获取,确保路径一致性) + File logDir = LogUtils.getLogCacheDir(); + if (logDir == null) { + LogUtils.d(TAG, "日志缓存目录未初始化,线程退出"); + return; + } + String logDirPath = logDir.getPath(); + LogUtils.d(TAG, "启动日志文件监听,监听目录:" + logDirPath); - // 初始化日志文件监听器(监听目标目录的文件事件) - mLogListener = new LogListener(logDirPath); - // 开始监听文件事件(非阻塞,内部通过 Native 层实现) - mLogListener.startWatching(); + // 初始化日志文件监听器(监听目标目录的文件事件) + mLogListener = new LogListener(logDirPath); + // 开始监听文件事件(非阻塞,内部通过 Native 层实现) + mLogListener.startWatching(); - // 循环等待退出标志(每 1 秒检查一次,降低 CPU 占用) - while (!isExit()) { - try { - Thread.sleep(1000); // 休眠 1 秒,避免忙等 - } catch (InterruptedException e) { - // 线程被中断时,恢复中断标志并退出循环(避免无限阻塞) - Thread.currentThread().interrupt(); - LogUtils.d(TAG, "日志监听线程被中断,准备退出。" + e); - break; - } - } + // 循环等待退出标志(每 1 秒检查一次,降低 CPU 占用) + while (!isExit()) { + try { + Thread.sleep(1000); // 休眠 1 秒,避免忙等 + } catch (InterruptedException e) { + // 线程被中断时,恢复中断标志并退出循环(避免无限阻塞) + Thread.currentThread().interrupt(); + LogUtils.d(TAG, "日志监听线程被中断,准备退出。" + e); + break; + } + } - // 收到退出标志,停止监听并释放资源 - mLogListener.stopWatching(); - LogUtils.d(TAG, "日志文件监听已停止,线程退出"); + // 收到退出标志,停止监听并释放资源 + mLogListener.stopWatching(); + LogUtils.d(TAG, "日志文件监听已停止,线程退出"); + } } /** 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..af140aa --- /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 (T) 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, 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 = (T) 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(); + } +} +