From 0cfbc43acb138c489571038bf7dc3cad66b82ce2 Mon Sep 17 00:00:00 2001 From: ZhanGSKen Date: Mon, 22 Dec 2025 08:55:09 +0800 Subject: [PATCH] =?UTF-8?q?MemoryCachedBackgroundView=E6=B5=8B=E8=AF=95?= =?UTF-8?q?=E5=AE=8C=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- powerbell/build.properties | 4 +- powerbell/src/main/AndroidManifest.xml | 2 + .../studio/powerbell/MainActivity.java | 6 +- .../BackgroundSettingsActivity.java | 4 +- .../dialogs/NetworkBackgroundDialog.java | 2 +- .../unittest/MainUnitTest2Activity.java | 257 ++++++++++++++++++ .../unittest/MainUnitTestActivity.java | 4 +- .../powerbell/views/BackgroundView.java | 6 +- .../views/MemoryCachedBackgroundView.java | 14 +- .../res/layout/activity_mainunittest2.xml | 50 ++++ .../src/main/res/menu/toolbar_unittest.xml | 8 +- 11 files changed, 337 insertions(+), 20 deletions(-) create mode 100644 powerbell/src/main/java/cc/winboll/studio/powerbell/unittest/MainUnitTest2Activity.java create mode 100644 powerbell/src/main/res/layout/activity_mainunittest2.xml diff --git a/powerbell/build.properties b/powerbell/build.properties index 5bdab7a..1e82604 100644 --- a/powerbell/build.properties +++ b/powerbell/build.properties @@ -1,8 +1,8 @@ #Created by .winboll/winboll_app_build.gradle -#Sun Dec 21 19:13:50 HKT 2025 +#Mon Dec 22 00:53:45 GMT 2025 stageCount=18 libraryProject= baseVersion=15.14 publishVersion=15.14.17 -buildCount=0 +buildCount=7 baseBetaVersion=15.14.18 diff --git a/powerbell/src/main/AndroidManifest.xml b/powerbell/src/main/AndroidManifest.xml index ebac690..76160eb 100644 --- a/powerbell/src/main/AndroidManifest.xml +++ b/powerbell/src/main/AndroidManifest.xml @@ -288,6 +288,8 @@ + + \ No newline at end of file diff --git a/powerbell/src/main/java/cc/winboll/studio/powerbell/MainActivity.java b/powerbell/src/main/java/cc/winboll/studio/powerbell/MainActivity.java index 10d1103..d2d62e2 100644 --- a/powerbell/src/main/java/cc/winboll/studio/powerbell/MainActivity.java +++ b/powerbell/src/main/java/cc/winboll/studio/powerbell/MainActivity.java @@ -28,6 +28,7 @@ import cc.winboll.studio.powerbell.activities.WinBoLLActivity; import cc.winboll.studio.powerbell.models.BackgroundBean; import cc.winboll.studio.powerbell.models.ControlCenterServiceBean; import cc.winboll.studio.powerbell.services.ControlCenterService; +import cc.winboll.studio.powerbell.unittest.MainUnitTest2Activity; import cc.winboll.studio.powerbell.unittest.MainUnitTestActivity; import cc.winboll.studio.powerbell.utils.AppConfigUtils; import cc.winboll.studio.powerbell.utils.BackgroundSourceUtils; @@ -210,6 +211,9 @@ public class MainActivity extends WinBoLLActivity implements MainContentView.OnV break; case R.id.action_unittestactivity: startActivity(new Intent(this, MainUnitTestActivity.class)); + break; + case R.id.action_unittest2activity: + startActivity(new Intent(this, MainUnitTest2Activity.class)); break; case R.id.action_about: startAboutActivity(); @@ -402,7 +406,7 @@ public class MainActivity extends WinBoLLActivity implements MainContentView.OnV } BackgroundBean currentBgBean = mBgSourceUtils.getCurrentBackgroundBean(); if (currentBgBean != null) { - mMainContentView.backgroundView.loadBackgroundBean(currentBgBean); + mMainContentView.backgroundView.loadByBackgroundBean(currentBgBean); } else { mMainContentView.backgroundView.setBackgroundResource(R.drawable.default_background); } diff --git a/powerbell/src/main/java/cc/winboll/studio/powerbell/activities/BackgroundSettingsActivity.java b/powerbell/src/main/java/cc/winboll/studio/powerbell/activities/BackgroundSettingsActivity.java index 44aae1c..f094eb4 100644 --- a/powerbell/src/main/java/cc/winboll/studio/powerbell/activities/BackgroundSettingsActivity.java +++ b/powerbell/src/main/java/cc/winboll/studio/powerbell/activities/BackgroundSettingsActivity.java @@ -402,7 +402,7 @@ public class BackgroundSettingsActivity extends WinBoLLActivity { try { mBgSourceUtils.loadSettings(); BackgroundBean previewBean = mBgSourceUtils.getPreviewBackgroundBean(); - mBackgroundView.loadBackgroundBean(previewBean, true); + mBackgroundView.loadByBackgroundBean(previewBean, true); mBackgroundView.setBackgroundColor(previewBean.getPixelColor()); LogUtils.d(TAG, "【双重刷新】第一重完成"); } catch (Exception e) { @@ -418,7 +418,7 @@ public class BackgroundSettingsActivity extends WinBoLLActivity { try { mBgSourceUtils.loadSettings(); BackgroundBean previewBean = mBgSourceUtils.getPreviewBackgroundBean(); - mBackgroundView.loadBackgroundBean(previewBean, true); + mBackgroundView.loadByBackgroundBean(previewBean, true); mBackgroundView.setBackgroundColor(previewBean.getPixelColor()); LogUtils.d(TAG, "【双重刷新】第二重完成"); } catch (Exception e) { diff --git a/powerbell/src/main/java/cc/winboll/studio/powerbell/dialogs/NetworkBackgroundDialog.java b/powerbell/src/main/java/cc/winboll/studio/powerbell/dialogs/NetworkBackgroundDialog.java index 1bcbd33..0f94bb9 100644 --- a/powerbell/src/main/java/cc/winboll/studio/powerbell/dialogs/NetworkBackgroundDialog.java +++ b/powerbell/src/main/java/cc/winboll/studio/powerbell/dialogs/NetworkBackgroundDialog.java @@ -208,7 +208,7 @@ public class NetworkBackgroundDialog extends AlertDialog { mPreviewFilePath = previewFilePath; BackgroundSourceUtils utils = BackgroundSourceUtils.getInstance(mContext); utils.saveFileToPreviewBean(new File(mPreviewFilePath), mPreviewFileUrl); - mBackgroundView.loadBackgroundBean(utils.getPreviewBackgroundBean()); + mBackgroundView.loadByBackgroundBean(utils.getPreviewBackgroundBean()); } catch (Exception e) { e.printStackTrace(); mBackgroundView.setBackgroundResource(R.drawable.ic_launcher); diff --git a/powerbell/src/main/java/cc/winboll/studio/powerbell/unittest/MainUnitTest2Activity.java b/powerbell/src/main/java/cc/winboll/studio/powerbell/unittest/MainUnitTest2Activity.java new file mode 100644 index 0000000..a330e5d --- /dev/null +++ b/powerbell/src/main/java/cc/winboll/studio/powerbell/unittest/MainUnitTest2Activity.java @@ -0,0 +1,257 @@ +package cc.winboll.studio.powerbell.unittest; + +import android.content.Intent; +import android.os.Bundle; +import android.os.Environment; +import android.os.Handler; +import android.os.Looper; +import android.view.View; +import android.widget.Button; +import android.widget.LinearLayout; +import androidx.appcompat.app.AppCompatActivity; +import cc.winboll.studio.libappbase.LogUtils; +import cc.winboll.studio.libappbase.ToastUtils; +import cc.winboll.studio.powerbell.MainActivity; +import cc.winboll.studio.powerbell.R; +import cc.winboll.studio.powerbell.models.BackgroundBean; +import cc.winboll.studio.powerbell.utils.FileUtils; +import cc.winboll.studio.powerbell.utils.ImageCropUtils; +import cc.winboll.studio.powerbell.views.BackgroundView; +import cc.winboll.studio.powerbell.views.MemoryCachedBackgroundView; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; + +/** + * @Author ZhanGSKen&豆包大模型 + * @Date 2025/12/22 08:31 + * @Describe MainUnitTest2Activity + */ +public class MainUnitTest2Activity extends AppCompatActivity { + // ====================== 常量定义 ====================== + public static final String TAG = "MainUnitTest2Activity"; + public static final int REQUEST_CROP_IMAGE = 0; + private static final String ASSETS_TEST_IMAGE_PATH = "unittest/unittest-miku.png"; + + // ====================== 成员变量(移除所有Uri相关) ====================== + private MemoryCachedBackgroundView mMemoryCachedBackgroundView; + private String mAppPrivateDirPath; + private File mPrivateTestImageFile; // 仅用File,不用Uri + private File mPrivateCropImageFile; + BackgroundBean mPreviewBackgroundBean; + LinearLayout mllBackgroundView; + + // ====================== 生命周期方法 ====================== + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + LogUtils.d(TAG, "=== 页面 onCreate 启动 ==="); + + initBaseParams(); + initViewAndEvent(); + copyAssetsTestImageToPrivateDir(); + //loadBackgroundByFile(); // 直接用File加载 + mPreviewBackgroundBean = new BackgroundBean(); + mPreviewBackgroundBean.setBackgroundFileName(mPrivateTestImageFile.getName()); + mPreviewBackgroundBean.setBackgroundFilePath(mPrivateTestImageFile.getAbsolutePath()); + mPreviewBackgroundBean.setBackgroundScaledCompressFileName(mPrivateCropImageFile.getName()); + mPreviewBackgroundBean.setBackgroundScaledCompressFilePath(mPrivateCropImageFile.getAbsolutePath()); + mPreviewBackgroundBean.setIsUseBackgroundFile(true); + doubleRefreshPreview(); + + ToastUtils.show("单元测试页面启动完成"); + LogUtils.d(TAG, "=== 页面 onCreate 初始化结束 ==="); + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + LogUtils.d(TAG, "=== onActivityResult 回调 ==="); + if (requestCode == REQUEST_CROP_IMAGE) { + handleCropResult(resultCode); + } + } + + // ====================== 初始化相关方法 ====================== + private void initBaseParams() { + LogUtils.d(TAG, "初始化基础参数:工具类+私有目录+File"); + + // 私有目录(无需权限,无UID冲突) + mAppPrivateDirPath = getExternalFilesDir(Environment.DIRECTORY_PICTURES).getAbsolutePath() + "/PowerBellTest/"; + File privateDir = new File(mAppPrivateDirPath); + if (!privateDir.exists()) { + privateDir.mkdirs(); + LogUtils.d(TAG, "创建私有目录:" + mAppPrivateDirPath); + } + + // 初始化File(无Uri) + File refFile = new File(ASSETS_TEST_IMAGE_PATH); + String uniqueTestName = FileUtils.createUniqueFileName(refFile) + ".png"; + String uniqueCropName = uniqueTestName.replace(".png", "_crop.png"); + mPrivateTestImageFile = new File(mAppPrivateDirPath, uniqueTestName); + mPrivateCropImageFile = new File(mAppPrivateDirPath, uniqueCropName); + + LogUtils.d(TAG, "测试图File路径:" + mPrivateTestImageFile.getAbsolutePath()); + } + + private void initViewAndEvent() { + LogUtils.d(TAG, "初始化布局与控件事件"); + setContentView(R.layout.activity_mainunittest2); + mllBackgroundView = (LinearLayout) findViewById(R.id.ll_backgroundview); + mMemoryCachedBackgroundView = MemoryCachedBackgroundView.getInstance(this, "", false); + mllBackgroundView.addView(mMemoryCachedBackgroundView); + + //mMemoryCachedBackgroundView = (BackgroundView) findViewById(R.id.backgroundview); + + // 跳转主页面按钮 + Button btnMain = (Button) findViewById(R.id.btn_main_activity); + btnMain.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + LogUtils.d(TAG, "点击按钮:跳转主页面"); + startActivity(new Intent(MainUnitTest2Activity.this, MainActivity.class)); + } + }); + + // 裁剪按钮(直接用File路径启动,无Uri) + Button btnCrop = (Button) findViewById(R.id.btn_test_cropimage); + btnCrop.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + LogUtils.d(TAG, "点击按钮:启动裁剪(File路径版)"); + ToastUtils.show("准备启动图片裁剪"); + + if (mPrivateTestImageFile.exists() && mPrivateTestImageFile.length() > 100) { + startCropTestByFile(); // 直接传File + } else { + ToastUtils.show("测试图片未准备好,重新拷贝"); + copyAssetsTestImageToPrivateDir(); + } + } + }); + } + + // 从assets拷贝图片(不变,确保File存在) + private void copyAssetsTestImageToPrivateDir() { + LogUtils.d(TAG, "开始拷贝assets图片到私有目录"); + if (mPrivateTestImageFile.exists() && mPrivateTestImageFile.length() > 100) { + LogUtils.d(TAG, "图片已存在,无需拷贝"); + return; + } + + InputStream inputStream = null; + try { + inputStream = getAssets().open(ASSETS_TEST_IMAGE_PATH); + FileUtils.copyStreamToFile(inputStream, mPrivateTestImageFile); + LogUtils.d(TAG, "图片拷贝成功,大小:" + mPrivateTestImageFile.length() + "字节"); + } catch (IOException e) { + LogUtils.e(TAG, "图片拷贝失败:" + e.getMessage(), e); + ToastUtils.show("图片准备失败"); + } finally { + if (inputStream != null) { + try { + inputStream.close(); + } catch (IOException e) { + LogUtils.e(TAG, "关闭流失败:" + e.getMessage()); + } + } + } + } + + // ====================== 核心业务方法(全改为File路径) ====================== + /** 直接用File路径加载背景图(无Uri,无冲突) */ +// private void loadBackgroundByFile() { +// LogUtils.d(TAG, "开始加载背景图(File路径版)"); +// if (mPrivateTestImageFile.exists() && mPrivateTestImageFile.length() > 100) { +// mBackgroundView.loadImage(mPrivateTestImageFile.getAbsolutePath()); // 直接传路径 +// LogUtils.d(TAG, "背景图加载成功:" + mPrivateTestImageFile.getAbsolutePath()); +// ToastUtils.show("背景图加载成功"); +// } else { +// LogUtils.e(TAG, "背景图加载失败:文件无效"); +// ToastUtils.show("背景图加载失败"); +// } +// } + + /** 直接用File启动裁剪(关键:调用ImageCropUtils的File重载方法) */ + private void startCropTestByFile() { + LogUtils.d(TAG, "启动裁剪(File路径版),原图:" + mPrivateTestImageFile.getAbsolutePath()); + + // 确保输出目录存在 + File cropParent = mPrivateCropImageFile.getParentFile(); + if (!cropParent.exists()) { + cropParent.mkdirs(); + } + + // 调用ImageCropUtils的File参数方法(核心:绕开Uri) + ImageCropUtils.startImageCrop( + this, + mPrivateTestImageFile, // 原图File + mPrivateCropImageFile, // 输出File + 0, + 0, + true, + REQUEST_CROP_IMAGE + ); + + LogUtils.d(TAG, "裁剪请求已发送,输出路径:" + mPrivateCropImageFile.getAbsolutePath()); + ToastUtils.show("已启动图片裁剪"); + } + + /** 处理裁剪结果(直接校验输出File) */ + private void handleCropResult(int resultCode) { + LogUtils.d(TAG, "裁剪回调处理:resultCode=" + resultCode); + if (resultCode == RESULT_OK) { + if (mPrivateCropImageFile.exists() && mPrivateCropImageFile.length() > 100) { + mMemoryCachedBackgroundView.loadImage(mPrivateCropImageFile.getAbsolutePath()); + LogUtils.d(TAG, "裁剪成功,加载裁剪图:" + mPrivateCropImageFile.getAbsolutePath()); + ToastUtils.show("裁剪成功"); + mPreviewBackgroundBean.setIsUseBackgroundScaledCompressFile(true); + doubleRefreshPreview(); + } else { + LogUtils.e(TAG, "裁剪成功但输出文件无效"); + ToastUtils.show("裁剪失败:输出文件无效"); + } + } else if (resultCode == RESULT_CANCELED) { + LogUtils.d(TAG, "裁剪取消"); + ToastUtils.show("裁剪已取消"); + } else { + LogUtils.e(TAG, "裁剪失败:resultCode异常"); + ToastUtils.show("裁剪失败"); + } + } + + + /** + * 双重刷新预览,确保背景加载最新数据 + * 移除:缓存清空逻辑 + */ + private void doubleRefreshPreview() { + + // 第一重刷新 + try { + mMemoryCachedBackgroundView.loadByBackgroundBean(mPreviewBackgroundBean, true); + mMemoryCachedBackgroundView.setBackgroundColor(mPreviewBackgroundBean.getPixelColor()); + LogUtils.d(TAG, "【双重刷新】第一重完成"); + } catch (Exception e) { + LogUtils.e(TAG, "【双重刷新】第一重异常:" + e.getMessage()); + return; + } + + // 第二重刷新(延迟执行) + new Handler(Looper.getMainLooper()).postDelayed(new Runnable() { + @Override + public void run() { + if (mMemoryCachedBackgroundView != null && !isFinishing()) { + try { + mMemoryCachedBackgroundView.loadByBackgroundBean(mPreviewBackgroundBean, true); + mMemoryCachedBackgroundView.setBackgroundColor(mPreviewBackgroundBean.getPixelColor()); + LogUtils.d(TAG, "【双重刷新】第二重完成"); + } catch (Exception e) { + LogUtils.e(TAG, "【双重刷新】第二重异常:" + e.getMessage()); + } + } + } + }, 200); + } +} + diff --git a/powerbell/src/main/java/cc/winboll/studio/powerbell/unittest/MainUnitTestActivity.java b/powerbell/src/main/java/cc/winboll/studio/powerbell/unittest/MainUnitTestActivity.java index 619465e..ab4b0de 100644 --- a/powerbell/src/main/java/cc/winboll/studio/powerbell/unittest/MainUnitTestActivity.java +++ b/powerbell/src/main/java/cc/winboll/studio/powerbell/unittest/MainUnitTestActivity.java @@ -221,7 +221,7 @@ public class MainUnitTestActivity extends AppCompatActivity { // 第一重刷新 try { - mBackgroundView.loadBackgroundBean(mPreviewBackgroundBean, true); + mBackgroundView.loadByBackgroundBean(mPreviewBackgroundBean, true); mBackgroundView.setBackgroundColor(mPreviewBackgroundBean.getPixelColor()); LogUtils.d(TAG, "【双重刷新】第一重完成"); } catch (Exception e) { @@ -235,7 +235,7 @@ public class MainUnitTestActivity extends AppCompatActivity { public void run() { if (mBackgroundView != null && !isFinishing()) { try { - mBackgroundView.loadBackgroundBean(mPreviewBackgroundBean, true); + mBackgroundView.loadByBackgroundBean(mPreviewBackgroundBean, true); mBackgroundView.setBackgroundColor(mPreviewBackgroundBean.getPixelColor()); LogUtils.d(TAG, "【双重刷新】第二重完成"); } catch (Exception e) { diff --git a/powerbell/src/main/java/cc/winboll/studio/powerbell/views/BackgroundView.java b/powerbell/src/main/java/cc/winboll/studio/powerbell/views/BackgroundView.java index d5b7780..89b6ef8 100644 --- a/powerbell/src/main/java/cc/winboll/studio/powerbell/views/BackgroundView.java +++ b/powerbell/src/main/java/cc/winboll/studio/powerbell/views/BackgroundView.java @@ -104,11 +104,11 @@ public class BackgroundView extends RelativeLayout { LogUtils.d(TAG, "=== initImageView 完成 ==="); } - public void loadBackgroundBean(BackgroundBean bean) { - loadBackgroundBean(bean, false); + public void loadByBackgroundBean(BackgroundBean bean) { + loadByBackgroundBean(bean, false); } - public void loadBackgroundBean(BackgroundBean bean, boolean isRefresh) { + public void loadByBackgroundBean(BackgroundBean bean, boolean isRefresh) { if (!bean.isUseBackgroundFile()) { setDefaultTransparentBackground(); return; diff --git a/powerbell/src/main/java/cc/winboll/studio/powerbell/views/MemoryCachedBackgroundView.java b/powerbell/src/main/java/cc/winboll/studio/powerbell/views/MemoryCachedBackgroundView.java index c65d14d..1acc66e 100644 --- a/powerbell/src/main/java/cc/winboll/studio/powerbell/views/MemoryCachedBackgroundView.java +++ b/powerbell/src/main/java/cc/winboll/studio/powerbell/views/MemoryCachedBackgroundView.java @@ -20,17 +20,17 @@ public class MemoryCachedBackgroundView extends BackgroundView { private static final Map sViewCacheMap = new HashMap(); // ====================================== 构造器(继承并兼容父类) ====================================== - public MemoryCachedBackgroundView(Context context) { + private MemoryCachedBackgroundView(Context context) { super(context); LogUtils.d(TAG, "构造器1:创建MemoryCachedBackgroundView实例"); } - public MemoryCachedBackgroundView(Context context, AttributeSet attrs) { + private MemoryCachedBackgroundView(Context context, AttributeSet attrs) { super(context, attrs); LogUtils.d(TAG, "构造器2:创建MemoryCachedBackgroundView实例"); } - public MemoryCachedBackgroundView(Context context, AttributeSet attrs, int defStyleAttr) { + private MemoryCachedBackgroundView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); LogUtils.d(TAG, "构造器3:创建MemoryCachedBackgroundView实例"); } @@ -113,15 +113,15 @@ public class MemoryCachedBackgroundView extends BackgroundView { } @Override - public void loadBackgroundBean(BackgroundBean bean) { + public void loadByBackgroundBean(BackgroundBean bean) { LogUtils.d(TAG, "loadBackgroundBean() 重载方法调用 | BackgroundBean:" + (bean == null ? "null" : bean.toString())); - super.loadBackgroundBean(bean); + super.loadByBackgroundBean(bean); } @Override - public void loadBackgroundBean(BackgroundBean bean, boolean isRefresh) { + public void loadByBackgroundBean(BackgroundBean bean, boolean isRefresh) { LogUtils.d(TAG, "loadBackgroundBean() 重载方法调用 | BackgroundBean:" + (bean == null ? "null" : bean.toString()) + " | 是否刷新:" + isRefresh); - super.loadBackgroundBean(bean, isRefresh); + super.loadByBackgroundBean(bean, isRefresh); } } diff --git a/powerbell/src/main/res/layout/activity_mainunittest2.xml b/powerbell/src/main/res/layout/activity_mainunittest2.xml new file mode 100644 index 0000000..04433e4 --- /dev/null +++ b/powerbell/src/main/res/layout/activity_mainunittest2.xml @@ -0,0 +1,50 @@ + + + + + + + + + + + + +