源码整理
This commit is contained in:
@@ -1,8 +1,8 @@
|
|||||||
#Created by .winboll/winboll_app_build.gradle
|
#Created by .winboll/winboll_app_build.gradle
|
||||||
#Wed Nov 12 20:21:00 GMT 2025
|
#Wed Nov 12 20:28:00 GMT 2025
|
||||||
stageCount=10
|
stageCount=10
|
||||||
libraryProject=libappbase
|
libraryProject=libappbase
|
||||||
baseVersion=15.10
|
baseVersion=15.10
|
||||||
publishVersion=15.10.9
|
publishVersion=15.10.9
|
||||||
buildCount=21
|
buildCount=22
|
||||||
baseBetaVersion=15.10.10
|
baseBetaVersion=15.10.10
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
#Created by .winboll/winboll_app_build.gradle
|
#Created by .winboll/winboll_app_build.gradle
|
||||||
#Wed Nov 12 20:21:00 GMT 2025
|
#Wed Nov 12 20:28:00 GMT 2025
|
||||||
stageCount=10
|
stageCount=10
|
||||||
libraryProject=libappbase
|
libraryProject=libappbase
|
||||||
baseVersion=15.10
|
baseVersion=15.10
|
||||||
publishVersion=15.10.9
|
publishVersion=15.10.9
|
||||||
buildCount=21
|
buildCount=22
|
||||||
baseBetaVersion=15.10.10
|
baseBetaVersion=15.10.10
|
||||||
|
|||||||
@@ -4,77 +4,138 @@ package cc.winboll.studio.libappbase;
|
|||||||
* @Author ZhanGSKen<zhangsken@qq.com>
|
* @Author ZhanGSKen<zhangsken@qq.com>
|
||||||
* @Date 2024/08/12 14:43:50
|
* @Date 2024/08/12 14:43:50
|
||||||
* @Describe 日志视图线程类
|
* @Describe 日志视图线程类
|
||||||
|
* 独立线程监听日志文件目录变化(如写入、删除),触发日志视图更新,避免阻塞主线程
|
||||||
*/
|
*/
|
||||||
import android.os.FileObserver;
|
import android.os.FileObserver;
|
||||||
import cc.winboll.studio.libappbase.LogUtils;
|
|
||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
|
|
||||||
public class LogViewThread extends Thread {
|
public class LogViewThread extends Thread {
|
||||||
|
|
||||||
|
/** 日志标签(用于调试输出) */
|
||||||
public static final String TAG = "LogViewThread";
|
public static final String TAG = "LogViewThread";
|
||||||
|
|
||||||
// 线程退出标志
|
/** 线程退出标志(volatile 保证多线程可见性,控制循环退出) */
|
||||||
volatile boolean isExist = false;
|
private volatile boolean isExit = false;
|
||||||
// 应用日志文件监听实例
|
/** 日志文件目录监听实例(监听文件写入、删除事件) */
|
||||||
LogListener mLogListener;
|
private LogListener mLogListener;
|
||||||
// 日志视图弱引用
|
/** 日志视图弱引用(避免持有 LogView 强引用导致内存泄漏) */
|
||||||
WeakReference<LogView> mwrLogView;
|
private final WeakReference<LogView> mLogViewWeakRef;
|
||||||
|
|
||||||
//
|
/**
|
||||||
// 构造函数
|
* 构造函数
|
||||||
// @logView : 日志显示输出视图类
|
* @param logView 日志显示视图实例(需通过弱引用持有,避免内存泄漏)
|
||||||
|
*/
|
||||||
public LogViewThread(LogView logView) {
|
public LogViewThread(LogView logView) {
|
||||||
mwrLogView = new WeakReference<LogView>(logView);
|
// 使用弱引用包装 LogView,当视图销毁时可被 GC 回收
|
||||||
|
mLogViewWeakRef = new WeakReference<>(logView);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setIsExist(boolean isExist) {
|
/**
|
||||||
this.isExist = isExist;
|
* 设置线程退出标志(触发线程停止监听并退出)
|
||||||
|
* @param exit true:退出线程;false:继续运行(默认)
|
||||||
|
*/
|
||||||
|
public void setExit(boolean exit) {
|
||||||
|
this.isExit = exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isExist() {
|
/**
|
||||||
return isExist;
|
* 获取当前线程退出状态
|
||||||
|
* @return true:已标记退出;false:运行中
|
||||||
|
*/
|
||||||
|
public boolean isExit() {
|
||||||
|
return isExit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 线程核心逻辑:初始化文件监听并启动循环,直到收到退出标志
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
String szLogDir = LogUtils.getLogCacheDir().getPath();
|
// 获取日志缓存目录路径(从 LogUtils 统一获取,确保路径一致性)
|
||||||
mLogListener = new LogListener(szLogDir);
|
String logDirPath = LogUtils.getLogCacheDir().getPath();
|
||||||
|
LogUtils.d(TAG, "启动日志文件监听,监听目录:" + logDirPath);
|
||||||
|
|
||||||
|
// 初始化日志文件监听器(监听目标目录的文件事件)
|
||||||
|
mLogListener = new LogListener(logDirPath);
|
||||||
|
// 开始监听文件事件(非阻塞,内部通过 Native 层实现)
|
||||||
mLogListener.startWatching();
|
mLogListener.startWatching();
|
||||||
while (isExist() == false) {
|
|
||||||
|
// 循环等待退出标志(每 1 秒检查一次,降低 CPU 占用)
|
||||||
|
while (!isExit()) {
|
||||||
try {
|
try {
|
||||||
Thread.sleep(1000);
|
Thread.sleep(1000); // 休眠 1 秒,避免忙等
|
||||||
} catch (InterruptedException e) {}
|
} catch (InterruptedException e) {
|
||||||
|
// 线程被中断时,恢复中断标志并退出循环(避免无限阻塞)
|
||||||
|
Thread.currentThread().interrupt();
|
||||||
|
LogUtils.d(TAG, "日志监听线程被中断,准备退出。" + e);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 收到退出标志,停止监听并释放资源
|
||||||
mLogListener.stopWatching();
|
mLogListener.stopWatching();
|
||||||
|
LogUtils.d(TAG, "日志文件监听已停止,线程退出");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 日志文件监听内部类(继承 FileObserver,监听目录下文件变化)
|
||||||
|
* 仅关注文件写入完成(CLOSE_WRITE)和文件删除(DELETE)事件
|
||||||
|
*/
|
||||||
|
private class LogListener extends FileObserver {
|
||||||
|
|
||||||
//
|
/**
|
||||||
// 日志文件监听类
|
* 构造函数
|
||||||
//
|
* @param path 监听的目录路径(此处为日志缓存目录)
|
||||||
class LogListener extends FileObserver {
|
*/
|
||||||
public LogListener(String path) {
|
public LogListener(String path) {
|
||||||
|
// 父类构造:监听指定目录的所有事件(通过位掩码 ALL_EVENTS 指定)
|
||||||
super(path);
|
super(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 文件事件回调(运行在系统私有线程,非主线程)
|
||||||
|
* @param event 事件类型(通过位掩码表示,需与 ALL_EVENTS 按位与解析)
|
||||||
|
* @param path 发生事件的文件名(相对监听目录的路径)
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void onEvent(int event, String path) {
|
public void onEvent(int event, String path) {
|
||||||
int e = event & FileObserver.ALL_EVENTS;
|
// 解析事件类型(排除无关事件,只处理目标事件)
|
||||||
switch (e) {
|
int eventType = event & FileObserver.ALL_EVENTS;
|
||||||
case FileObserver.CLOSE_WRITE:{
|
|
||||||
if (mwrLogView.get() != null) {
|
switch (eventType) {
|
||||||
mwrLogView.get().updateLogView();
|
// 事件:文件写入完成(如日志写入结束并关闭文件)
|
||||||
}
|
case FileObserver.CLOSE_WRITE:
|
||||||
break;
|
LogUtils.d(TAG, "日志文件写入完成,文件名:" + (path != null ? path : "未知"));
|
||||||
}
|
// 触发日志视图更新(需先判断 LogView 是否未被回收)
|
||||||
case FileObserver.DELETE:{
|
updateLogView();
|
||||||
if (mwrLogView.get() != null) {
|
break;
|
||||||
mwrLogView.get().updateLogView();
|
|
||||||
}
|
// 事件:文件被删除(如日志清理操作)
|
||||||
break;
|
case FileObserver.DELETE:
|
||||||
}
|
LogUtils.d(TAG, "日志文件被删除,文件名:" + (path != null ? path : "未知"));
|
||||||
|
// 触发日志视图更新(刷新视图显示空状态)
|
||||||
|
updateLogView();
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
// 忽略其他无关事件(如文件创建、访问等)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 触发日志视图更新(通过弱引用获取 LogView,避免内存泄漏)
|
||||||
|
*/
|
||||||
|
private void updateLogView() {
|
||||||
|
// 从弱引用中获取 LogView 实例(若视图已销毁,get() 返回 null)
|
||||||
|
LogView logView = mLogViewWeakRef.get();
|
||||||
|
if (logView != null) {
|
||||||
|
// 调用 LogView 的更新方法(需确保 updateLogView 内部处理主线程切换)
|
||||||
|
logView.updateLogView();
|
||||||
|
} else {
|
||||||
|
LogUtils.w(TAG, "LogView 已被回收,无法更新日志视图");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user