视图缓存控件调试成功。

This commit is contained in:
2025-12-25 16:00:17 +08:00
parent 4fcce7edb3
commit 81f0e5c56e
8 changed files with 70 additions and 51 deletions

View File

@@ -1,8 +1,8 @@
#Created by .winboll/winboll_app_build.gradle #Created by .winboll/winboll_app_build.gradle
#Thu Dec 25 07:32:14 GMT 2025 #Thu Dec 25 07:58:57 GMT 2025
stageCount=30 stageCount=30
libraryProject= libraryProject=
baseVersion=15.14 baseVersion=15.14
publishVersion=15.14.29 publishVersion=15.14.29
buildCount=36 buildCount=42
baseBetaVersion=15.14.30 baseBetaVersion=15.14.30

View File

@@ -198,7 +198,6 @@
android:priority="1000" android:priority="1000"
android:enabled="true" android:enabled="true"
android:exported="false" android:exported="false"
android:process=".controlcenterservice"
android:foregroundServiceType="dataSync"> android:foregroundServiceType="dataSync">
<property <property
android:name="android.app.PROPERTY_SPECIAL_USE_FOREGROUND_SERVICE" android:name="android.app.PROPERTY_SPECIAL_USE_FOREGROUND_SERVICE"
@@ -209,7 +208,7 @@
android:name=".services.AssistantService" android:name=".services.AssistantService"
android:enabled="true" android:enabled="true"
android:exported="false" android:exported="false"
android:process=".assistantservice"> android:process=".assistant">
<property <property
android:name="android.app.PROPERTY_SPECIAL_USE_FOREGROUND_SERVICE" android:name="android.app.PROPERTY_SPECIAL_USE_FOREGROUND_SERVICE"
android:value="辅助核心功能运行"/> android:value="辅助核心功能运行"/>

View File

@@ -18,6 +18,8 @@ import cc.winboll.studio.powerbell.views.MemoryCachedBackgroundView;
* 应用全局入口类适配Android API 30基于Java 7编写 * 应用全局入口类适配Android API 30基于Java 7编写
* 核心策略:极致强制缓存 - 无论内存紧张程度永不自动清理任何缓存Bitmap/视图控件/路径记录) * 核心策略:极致强制缓存 - 无论内存紧张程度永不自动清理任何缓存Bitmap/视图控件/路径记录)
* @Author 豆包&ZhanGSKen<zhangsken@qq.com> * @Author 豆包&ZhanGSKen<zhangsken@qq.com>
* @Version 1.0.0
* @Date 2025-12-25
*/ */
public class App extends GlobalApplication { public class App extends GlobalApplication {
// ===================== 常量定义区(按功能分类排序) ===================== // ===================== 常量定义区(按功能分类排序) =====================
@@ -35,6 +37,7 @@ public class App extends GlobalApplication {
// 缓存防护常量 // 缓存防护常量
private static final String CACHE_PROTECT_TAG = "FORCE_CACHE_PROTECT"; private static final String CACHE_PROTECT_TAG = "FORCE_CACHE_PROTECT";
private static final int INVALID_BATTERY_VALUE = -1;
// ===================== 静态属性区(按工具类优先级排序) ===================== // ===================== 静态属性区(按工具类优先级排序) =====================
// 数据配置工具 // 数据配置工具
@@ -46,7 +49,9 @@ public class App extends GlobalApplication {
public static BitmapCacheUtils sBitmapCacheUtils; public static BitmapCacheUtils sBitmapCacheUtils;
// 全局视图控件缓存工具(极致强制保持:一旦初始化,永不销毁) // 全局视图控件缓存工具(极致强制保持:一旦初始化,永不销毁)
public static MemoryCachedBackgroundView sMemoryCachedBackgroundView; // 核心修改:改为私有静态,通过实例方法获取,避免全局通用暴露
private static MemoryCachedBackgroundView sMemoryCachedBackgroundView;
public static volatile int sQuantityOfElectricity = INVALID_BATTERY_VALUE;
// ===================== 成员属性区(按生命周期关联度排序) ===================== // ===================== 成员属性区(按生命周期关联度排序) =====================
// 全局广播接收器 // 全局广播接收器
@@ -83,6 +88,13 @@ public class App extends GlobalApplication {
return sAppCacheUtils; return sAppCacheUtils;
} }
/**
* 获取应用单例实例
*/
public static App getInstance() {
return sApp;
}
// ===================== 公共成员方法区(业务功能) ===================== // ===================== 公共成员方法区(业务功能) =====================
/** /**
* 清除电池历史数据 * 清除电池历史数据
@@ -116,6 +128,17 @@ public class App extends GlobalApplication {
LogUtils.w(TAG, String.format("%s 手动清理缓存完成(部分缓存实例仍可能保留在内存中)", CACHE_PROTECT_TAG)); LogUtils.w(TAG, String.format("%s 手动清理缓存完成(部分缓存实例仍可能保留在内存中)", CACHE_PROTECT_TAG));
} }
/**
* 获取视图控件缓存实例非通用仅通过App实例调用避免全局直接访问
*/
public MemoryCachedBackgroundView getMemoryCachedBackgroundView() {
LogUtils.d(TAG, "getMemoryCachedBackgroundView() 调用 | 视图控件缓存实例获取");
if (sMemoryCachedBackgroundView == null) {
LogUtils.w(TAG, "getMemoryCachedBackgroundView()视图控件缓存实例未初始化返回null");
}
return sMemoryCachedBackgroundView;
}
// ===================== 生命周期方法区(按执行顺序排序) ===================== // ===================== 生命周期方法区(按执行顺序排序) =====================
@Override @Override
public void onCreate() { public void onCreate() {
@@ -207,7 +230,7 @@ public class App extends GlobalApplication {
// 极致强制初始化视图控件缓存工具(必初始化,永不销毁) // 极致强制初始化视图控件缓存工具(必初始化,永不销毁)
sMemoryCachedBackgroundView = MemoryCachedBackgroundView.getLastInstance(this); sMemoryCachedBackgroundView = MemoryCachedBackgroundView.getLastInstance(this);
if (sMemoryCachedBackgroundView == null) { if (sMemoryCachedBackgroundView == null) {
App.notifyMessage(TAG, "sMemoryCachedBackgroundView == null"); //App.notifyMessage(TAG, "sMemoryCachedBackgroundView == null");
sMemoryCachedBackgroundView = MemoryCachedBackgroundView.getInstance(this, sBackgroundSourceUtils.getCurrentBackgroundBean(), true); sMemoryCachedBackgroundView = MemoryCachedBackgroundView.getInstance(this, sBackgroundSourceUtils.getCurrentBackgroundBean(), true);
} }
LogUtils.d(TAG, "initUtils() 视图控件缓存工具已初始化(极致强制保持,永不销毁)"); LogUtils.d(TAG, "initUtils() 视图控件缓存工具已初始化(极致强制保持,永不销毁)");

View File

@@ -5,10 +5,10 @@ import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.IntentFilter; import android.content.IntentFilter;
import cc.winboll.studio.libappbase.LogUtils; import cc.winboll.studio.libappbase.LogUtils;
import cc.winboll.studio.powerbell.App;
import cc.winboll.studio.powerbell.models.AppConfigBean; import cc.winboll.studio.powerbell.models.AppConfigBean;
import cc.winboll.studio.powerbell.models.NotificationMessage; import cc.winboll.studio.powerbell.models.NotificationMessage;
import cc.winboll.studio.powerbell.services.ControlCenterService; import cc.winboll.studio.powerbell.services.ControlCenterService;
import cc.winboll.studio.powerbell.threads.RemindThread;
import cc.winboll.studio.powerbell.utils.AppConfigUtils; import cc.winboll.studio.powerbell.utils.AppConfigUtils;
import cc.winboll.studio.powerbell.utils.BatteryUtils; import cc.winboll.studio.powerbell.utils.BatteryUtils;
import cc.winboll.studio.powerbell.utils.NotificationManagerUtils; import cc.winboll.studio.powerbell.utils.NotificationManagerUtils;
@@ -142,7 +142,7 @@ public class ControlCenterServiceReceiver extends BroadcastReceiver {
latestConfig.getChargeReminderValue(), latestConfig.getUsageReminderValue())); latestConfig.getChargeReminderValue(), latestConfig.getUsageReminderValue()));
// 同步缓存的电池状态到配置 // 同步缓存的电池状态到配置
RemindThread.sQuantityOfElectricity = sLastBatteryLevel; App.sQuantityOfElectricity = sLastBatteryLevel;
latestConfig.setIsCharging(sIsCharging); latestConfig.setIsCharging(sIsCharging);
service.notifyAppConfigUpdate(latestConfig); service.notifyAppConfigUpdate(latestConfig);

View File

@@ -3,6 +3,7 @@ package cc.winboll.studio.powerbell.threads;
import android.content.Context; import android.content.Context;
import android.os.Message; import android.os.Message;
import cc.winboll.studio.libappbase.LogUtils; import cc.winboll.studio.libappbase.LogUtils;
import cc.winboll.studio.powerbell.App;
import cc.winboll.studio.powerbell.handlers.ControlCenterServiceHandler; import cc.winboll.studio.powerbell.handlers.ControlCenterServiceHandler;
import cc.winboll.studio.powerbell.models.AppConfigBean; import cc.winboll.studio.powerbell.models.AppConfigBean;
import java.lang.ref.WeakReference; import java.lang.ref.WeakReference;
@@ -26,7 +27,6 @@ public class RemindThread extends Thread {
private static final long THREAD_JOIN_TIMEOUT = 1000L; private static final long THREAD_JOIN_TIMEOUT = 1000L;
// 状态常量 // 状态常量
private static final int INVALID_BATTERY_VALUE = -1;
private static final int BATTERY_LEVEL_MIN = 0; private static final int BATTERY_LEVEL_MIN = 0;
private static final int BATTERY_LEVEL_MAX = 100; private static final int BATTERY_LEVEL_MAX = 100;
@@ -55,7 +55,6 @@ public class RemindThread extends Thread {
private volatile long sleepTime; private volatile long sleepTime;
private volatile int chargeReminderValue; private volatile int chargeReminderValue;
private volatile int usageReminderValue; private volatile int usageReminderValue;
public static volatile int sQuantityOfElectricity = INVALID_BATTERY_VALUE;
private volatile boolean isCharging; private volatile boolean isCharging;
// ====================== 私有构造器(禁止外部实例化) ====================== // ====================== 私有构造器(禁止外部实例化) ======================
@@ -170,21 +169,21 @@ public class RemindThread extends Thread {
if (isExist) break; if (isExist) break;
// 电量有效性校验非0-100视为无效退出电量提醒线程 // 电量有效性校验非0-100视为无效退出电量提醒线程
if (sQuantityOfElectricity < BATTERY_LEVEL_MIN || sQuantityOfElectricity > BATTERY_LEVEL_MAX) { if (App.sQuantityOfElectricity < BATTERY_LEVEL_MIN || App.sQuantityOfElectricity > BATTERY_LEVEL_MAX) {
LogUtils.w(TAG, String.format("电量无效,退出电量提醒线程 | 当前电量=%d | threadId=%d", sQuantityOfElectricity, getId())); LogUtils.w(TAG, String.format("电量无效,退出电量提醒线程 | 当前电量=%d | threadId=%d", App.sQuantityOfElectricity, getId()));
break; break;
} }
// 充电/耗电提醒触发逻辑 // 充电/耗电提醒触发逻辑
boolean chargeRemindTrigger = isCharging && isEnableChargeReminder && sQuantityOfElectricity >= chargeReminderValue; boolean chargeRemindTrigger = isCharging && isEnableChargeReminder && App.sQuantityOfElectricity >= chargeReminderValue;
boolean usageRemindTrigger = !isCharging && isEnableUsageReminder && sQuantityOfElectricity <= usageReminderValue; boolean usageRemindTrigger = !isCharging && isEnableUsageReminder && App.sQuantityOfElectricity <= usageReminderValue;
if (chargeRemindTrigger) { if (chargeRemindTrigger) {
LogUtils.d(TAG, String.format("触发充电提醒 | 当前电量=%d ≥ 阈值=%d | threadId=%d", sQuantityOfElectricity, chargeReminderValue, getId())); LogUtils.d(TAG, String.format("触发充电提醒 | 当前电量=%d ≥ 阈值=%d | threadId=%d", App.sQuantityOfElectricity, chargeReminderValue, getId()));
sendNotificationMessageInternal(REMIND_TYPE_CHARGE, sQuantityOfElectricity, isCharging); sendNotificationMessageInternal(REMIND_TYPE_CHARGE, App.sQuantityOfElectricity, isCharging);
} else if (usageRemindTrigger) { } else if (usageRemindTrigger) {
LogUtils.d(TAG, String.format("触发耗电提醒 | 当前电量=%d ≤ 阈值=%d | threadId=%d", sQuantityOfElectricity, usageReminderValue, getId())); LogUtils.d(TAG, String.format("触发耗电提醒 | 当前电量=%d ≤ 阈值=%d | threadId=%d", App.sQuantityOfElectricity, usageReminderValue, getId()));
sendNotificationMessageInternal(REMIND_TYPE_USAGE, sQuantityOfElectricity, isCharging); sendNotificationMessageInternal(REMIND_TYPE_USAGE, App.sQuantityOfElectricity, isCharging);
} else { } else {
LogUtils.d(TAG, String.format("未有合适类型提醒,退出提醒线程 | threadId=%d", getId())); LogUtils.d(TAG, String.format("未有合适类型提醒,退出提醒线程 | threadId=%d", getId()));
break; break;
@@ -194,7 +193,7 @@ public class RemindThread extends Thread {
safeSleepInternal(sleepTime); safeSleepInternal(sleepTime);
} catch (Exception e) { } catch (Exception e) {
LogUtils.e(TAG, String.format("循环运行异常,退出电量提醒线程 | 当前电量=%d | threadId=%d", sQuantityOfElectricity, getId()), e); LogUtils.e(TAG, String.format("循环运行异常,退出电量提醒线程 | 当前电量=%d | threadId=%d", App.sQuantityOfElectricity, getId()), e);
break; break;
} }
} }
@@ -283,7 +282,6 @@ public class RemindThread extends Thread {
LogUtils.d(TAG, String.format("cleanThreadStateInternal() 调用 | threadId=%d", getId())); LogUtils.d(TAG, String.format("cleanThreadStateInternal() 调用 | threadId=%d", getId()));
isReminding = false; isReminding = false;
isExist = true; isExist = true;
sQuantityOfElectricity = INVALID_BATTERY_VALUE;
// 中断当前线程(如果存活) // 中断当前线程(如果存活)
if (isAlive()) { if (isAlive()) {
interrupt(); interrupt();
@@ -300,7 +298,6 @@ public class RemindThread extends Thread {
LogUtils.d(TAG, String.format("setAppConfigBean() 调用 | config=%s | threadId=%d", config, getId())); LogUtils.d(TAG, String.format("setAppConfigBean() 调用 | config=%s | threadId=%d", config, getId()));
if (config == null) { if (config == null) {
LogUtils.e(TAG, String.format("配置同步失败配置Bean为空 | threadId=%d", getId())); LogUtils.e(TAG, String.format("配置同步失败配置Bean为空 | threadId=%d", getId()));
sQuantityOfElectricity = INVALID_BATTERY_VALUE;
return; return;
} }
@@ -315,7 +312,7 @@ public class RemindThread extends Thread {
isCharging = config.isCharging(); isCharging = config.isCharging();
LogUtils.d(TAG, String.format("配置同步完成 | 休眠时间=%dms | 充电提醒=%b | 耗电提醒=%b | 当前电量=%d | 充电阈值=%d | 耗电阈值=%d | threadId=%d", LogUtils.d(TAG, String.format("配置同步完成 | 休眠时间=%dms | 充电提醒=%b | 耗电提醒=%b | 当前电量=%d | 充电阈值=%d | 耗电阈值=%d | threadId=%d",
sleepTime, isEnableChargeReminder, isEnableUsageReminder, sQuantityOfElectricity, chargeReminderValue, usageReminderValue, getId())); sleepTime, isEnableChargeReminder, isEnableUsageReminder, App.sQuantityOfElectricity, chargeReminderValue, usageReminderValue, getId()));
} }
/** /**
@@ -348,7 +345,7 @@ public class RemindThread extends Thread {
", isReminding=" + isReminding + ", isReminding=" + isReminding +
", chargeThreshold=" + chargeReminderValue + ", chargeThreshold=" + chargeReminderValue +
", usageThreshold=" + usageReminderValue + ", usageThreshold=" + usageReminderValue +
", currentBattery=" + sQuantityOfElectricity + ", currentBattery=" + App.sQuantityOfElectricity +
", isCharging=" + isCharging + ", isCharging=" + isCharging +
", sleepTime=" + sleepTime + "ms" + ", sleepTime=" + sleepTime + "ms" +
'}'; '}';

View File

@@ -249,12 +249,12 @@ public class AppConfigUtils {
LogUtils.d(TAG, String.format("setCurrentBatteryValue() 调用 | 传入电量=%d", value)); LogUtils.d(TAG, String.format("setCurrentBatteryValue() 调用 | 传入电量=%d", value));
int calibratedValue = Math.min(Math.max(value, MIN_REMINDER_VALUE), MAX_REMINDER_VALUE); int calibratedValue = Math.min(Math.max(value, MIN_REMINDER_VALUE), MAX_REMINDER_VALUE);
if (calibratedValue == RemindThread.sQuantityOfElectricity) { if (calibratedValue == App.sQuantityOfElectricity) {
LogUtils.d(TAG, "setCurrentBatteryValue():电池电量无变化,无需操作"); LogUtils.d(TAG, "setCurrentBatteryValue():电池电量无变化,无需操作");
return; return;
} }
RemindThread.sQuantityOfElectricity = calibratedValue; App.sQuantityOfElectricity = calibratedValue;
LogUtils.d(TAG, String.format("setCurrentBatteryValue() 成功 | 电池电量=%d%%", calibratedValue)); LogUtils.d(TAG, String.format("setCurrentBatteryValue() 成功 | 电池电量=%d%%", calibratedValue));
} }
@@ -263,7 +263,7 @@ public class AppConfigUtils {
* @return 当前电池电量0-100 * @return 当前电池电量0-100
*/ */
public int getCurrentBatteryValue() { public int getCurrentBatteryValue() {
int value = RemindThread.sQuantityOfElectricity; int value = App.sQuantityOfElectricity;
LogUtils.d(TAG, String.format("getCurrentBatteryValue():获取电池电量=%d%%", value)); LogUtils.d(TAG, String.format("getCurrentBatteryValue():获取电池电量=%d%%", value));
return value; return value;
} }

View File

@@ -154,11 +154,11 @@ public class MainContentView {
mainLayout = (RelativeLayout) rootView.findViewById(R.id.activitymainRelativeLayout1); mainLayout = (RelativeLayout) rootView.findViewById(R.id.activitymainRelativeLayout1);
mllBackgroundView = (LinearLayout) rootView.findViewById(R.id.ll_backgroundview); mllBackgroundView = (LinearLayout) rootView.findViewById(R.id.ll_backgroundview);
backgroundView = App.sMemoryCachedBackgroundView.getLastInstance(mContext); backgroundView = App.getInstance().getMemoryCachedBackgroundView().getLastInstance(mContext);
if (backgroundView == null) { if (backgroundView == null) {
App.sBackgroundSourceUtils.loadSettings(); App.sBackgroundSourceUtils.loadSettings();
BackgroundBean backgroundBean = App.sBackgroundSourceUtils.getCurrentBackgroundBean(); BackgroundBean backgroundBean = App.sBackgroundSourceUtils.getCurrentBackgroundBean();
backgroundView = App.sMemoryCachedBackgroundView.getInstance(mContext, backgroundBean, true); backgroundView = App.getInstance().getMemoryCachedBackgroundView().getInstance(mContext, backgroundBean, true);
} }
if (backgroundView.getParent() != null) { if (backgroundView.getParent() != null) {
((ViewGroup) backgroundView.getParent()).removeView(backgroundView); ((ViewGroup) backgroundView.getParent()).removeView(backgroundView);

View File

@@ -65,7 +65,7 @@ public class MemoryCachedBackgroundView extends BackgroundView {
sCachedView.loadByBackgroundBean(bean, isReload); sCachedView.loadByBackgroundBean(bean, isReload);
saveLastLoadImagePath(context, getBackgroundBeanImagePath(bean)); saveLastLoadImagePath(context, getBackgroundBeanImagePath(bean));
LogUtils.d(TAG, String.format("getInstance: 已更新当前缓存实例,旧实例路径=%s强制保持", getBackgroundBeanImagePath(bean))); LogUtils.d(TAG, String.format("getInstance: 已更新当前缓存实例,旧实例路径=%s强制保持", getBackgroundBeanImagePath(bean)));
App.notifyMessage(TAG, String.format("getInstance: 已更新当前缓存实例,旧实例路径=%s强制保持", getBackgroundBeanImagePath(bean))); //App.notifyMessage(TAG, String.format("getInstance: 已更新当前缓存实例,旧实例路径=%s强制保持", getBackgroundBeanImagePath(bean)));
return sCachedView; return sCachedView;
} }
@@ -96,10 +96,10 @@ public class MemoryCachedBackgroundView extends BackgroundView {
//App.notifyMessage(TAG, String.format("lastPath : %s", lastPath)); //App.notifyMessage(TAG, String.format("lastPath : %s", lastPath));
if (lastPath.equals(sCachedImagePath) && sCachedView != null) { if (lastPath.equals(sCachedImagePath) && sCachedView != null) {
LogUtils.d(TAG, String.format("getLastInstance: 使用最后路径缓存实例 | 路径=%s", lastPath)); LogUtils.d(TAG, String.format("getLastInstance: 使用最后路径缓存实例 | 路径=%s", lastPath));
App.notifyMessage(TAG, String.format("getLastInstance: 使用最后路径缓存实例 | 路径=%s", lastPath)); //App.notifyMessage(TAG, String.format("getLastInstance: 使用最后路径缓存实例 | 路径=%s", lastPath));
return sCachedView; return sCachedView;
} }
App.notifyMessage(TAG, "getLastInstance 返回 null"); //App.notifyMessage(TAG, "getLastInstance 返回 null");
return null; return null;
} }