Android應用緩存清理利器:WorkManager深度實踐指南

本文將帶你全面掌握使用WorkManager實現緩存清理的技術方案,從基礎原理到性能優化,提供完整代碼實現和工程實踐指南

一、緩存清理的必要性與挑戰

在Android應用開發中,緩存管理是優化應用性能的關鍵環節。隨著應用使用時間增長,緩存文件可能占用大量存儲空間,影響用戶體驗。根據統計:

  • 平均應用緩存占用可達100MB-1GB
  • 75%的用戶會因存儲空間不足卸載應用
  • 定期清理可提升應用評分0.3-0.5分

傳統清理方案存在的問題:

  • 時機不當:用戶手動清理體驗差
  • 資源占用:清理時可能影響應用性能
  • 可靠性低:應用被殺后任務無法繼續

二、WorkManager:后臺任務的終極解決方案

WorkManager作為Android Jetpack的一部分,提供了強大的后臺任務管理能力:

特性說明優勢
向后兼容自動選擇最佳實現(JobScheduler, AlarmManager等)兼容API 14+
任務約束支持網絡、電量、存儲等條件智能執行
任務鏈支持順序/并行任務復雜任務處理
持久化設備重啟后任務自動恢復高可靠性
監控提供任務狀態監聽便于調試

WorkManager架構解析

API 23+
API 14-22
開發者
定義Worker
配置WorkRequest
WorkManager
系統API
JobScheduler
AlarmManager + Broadcast
系統執行任務
回調結果

三、完整實現方案

1. 添加依賴

在app模塊的build.gradle中:

dependencies {def work_version = "2.9.0"implementation "androidx.work:work-runtime-ktx:$work_version"// 可選 - 測試支持androidTestImplementation "androidx.work:work-testing:$work_version"
}

2. 緩存清理Worker實現

完整代碼實現

import android.content.Context
import androidx.work.CoroutineWorker
import androidx.work.WorkerParameters
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import java.io.File
import kotlin.math.minclass CacheCleanerWorker(context: Context,params: WorkerParameters
) : CoroutineWorker(context, params) {// 清理閾值:只清理7天前的文件private companion object {const val CLEANUP_THRESHOLD_DAYS = 7const val MAX_FILES_PER_BATCH = 50 // 每批次最大文件數}override suspend fun doWork(): Result = withContext(Dispatchers.IO) {return@withContext try {val startTime = System.currentTimeMillis()// 清理內部緩存val internalCacheCleaned = cleanCacheDir(applicationContext.cacheDir)// 清理外部緩存val externalCacheCleaned = applicationContext.externalCacheDir?.let {cleanCacheDir(it)} ?: 0// 清理自定義緩存目錄val customCacheDir = File(applicationContext.filesDir, "custom_cache")val customCacheCleaned = cleanCacheDir(customCacheDir)val totalCleaned = internalCacheCleaned + externalCacheCleaned + customCacheCleanedval timeSpent = System.currentTimeMillis() - startTime// 記錄清理結果logCleanupResult(totalCleaned, timeSpent)Result.success()} catch (e: SecurityException) {// 處理權限問題Result.failure()} catch (e: Exception) {// 其他異常處理Result.retry()}}/*** 遞歸清理緩存目錄* @return 刪除的文件數量*/private fun cleanCacheDir(cacheDir: File?): Int {if (cacheDir == null || !cacheDir.exists()) return 0var deletedCount = 0val thresholdTime = System.currentTimeMillis() - CLEANUP_THRESHOLD_DAYS * 24 * 3600 * 1000// 處理目錄下的文件cacheDir.listFiles()?.let { files ->for (file in files) {if (deletedCount >= MAX_FILES_PER_BATCH) {// 達到批次限制,暫停清理break}if (file.isDirectory) {// 遞歸清理子目錄deletedCount += cleanCacheDir(file)// 刪除空目錄if (file.list()?.isEmpty() == true) {file.delete()}} else {// 刪除過期文件if (file.lastModified() < thresholdTime) {if (file.delete()) {deletedCount++}}}}}return deletedCount}private fun logCleanupResult(fileCount: Int, timeSpent: Long) {// 實際項目中可接入分析工具println("緩存清理完成: 刪除 $fileCount 個文件, 耗時 ${timeSpent}ms")}
}

關鍵優化點

  1. 分批處理:設置MAX_FILES_PER_BATCH防止一次性處理過多文件阻塞系統
  2. 時間閾值:只清理超過7天的文件,保留近期緩存
  3. 空目錄處理:遞歸清理后刪除空目錄
  4. 性能監控:記錄清理時間和文件數量
  5. 異常處理:區分不同異常類型采取不同策略

3. 任務調度與配置

高級調度器實現

import android.content.Context
import androidx.work.Constraints
import androidx.work.ExistingPeriodicWorkPolicy
import androidx.work.NetworkType
import androidx.work.PeriodicWorkRequest
import androidx.work.PeriodicWorkRequestBuilder
import androidx.work.WorkManager
import java.util.concurrent.TimeUnitobject CacheCleanerScheduler {// 唯一任務名稱private const val UNIQUE_WORK_NAME = "cache_cleaner_work"// 不同構建環境使用不同策略fun schedule(context: Context) {val workManager = WorkManager.getInstance(context)// 取消可能存在的舊任務workManager.cancelUniqueWork(UNIQUE_WORK_NAME)// 構建約束條件val constraints = buildConstraints()// 創建定期工作請求val workRequest = buildWorkRequest(constraints)// 使用唯一任務名稱避免重復調度workManager.enqueueUniquePeriodicWork(UNIQUE_WORK_NAME,ExistingPeriodicWorkPolicy.REPLACE,workRequest)}private fun buildConstraints(): Constraints {return Constraints.Builder().setRequiresCharging(true) // 充電時執行.setRequiresBatteryNotLow(true) // 電量充足.setRequiresStorageNotLow(true) // 存儲空間充足.setRequiresDeviceIdle(true) // 設備空閑.setRequiredNetworkType(NetworkType.UNMETERED) // 僅限WiFi.build()}private fun buildWorkRequest(constraints: Constraints): PeriodicWorkRequest {val intervalHours = if (BuildConfig.DEBUG) {4 // 調試模式下4小時一次} else {24 // 生產環境24小時一次}val flexInterval = if (BuildConfig.DEBUG) {1 // 調試模式靈活間隔1小時} else {3 // 生產環境靈活間隔3小時}return PeriodicWorkRequestBuilder<CacheCleanerWorker>(intervalHours.toLong(), TimeUnit.HOURS,flexInterval.toLong(),TimeUnit.HOURS).setConstraints(constraints).setInitialDelay(calculateInitialDelay()) // 隨機初始延遲.addTag("cache_cleanup") // 添加標簽便于查詢.build()}/*** 計算隨機初始延遲(1-6小時)* 避免所有設備同時執行清理任務*/private fun calculateInitialDelay(): Long {val randomHours = (1..6).random()return randomHours.toLong()}// 取消任務fun cancel(context: Context) {WorkManager.getInstance(context).cancelUniqueWork(UNIQUE_WORK_NAME)}// 查詢任務狀態fun getWorkInfo(context: Context) {WorkManager.getInstance(context).getWorkInfosForUniqueWorkLiveData(UNIQUE_WORK_NAME).observeForever { workInfos ->workInfos?.forEach { info ->println("任務狀態: ${info.state}, ID: ${info.id}")}}}
}

調度策略解析

  1. 智能約束:只在設備充電、空閑、存儲充足且連接WiFi時執行
  2. 靈活間隔:使用flexInterval讓系統在時間窗內選擇最佳執行時機
  3. 隨機延遲:避免所有用戶同時執行導致服務器壓力
  4. 環境區分:調試模式更頻繁執行便于測試
  5. 任務管理:提供取消和狀態查詢接口

4. 應用啟動與配置

Application類配置

class MyApp : Application() {override fun onCreate() {super.onCreate()// 初始化WorkManagerinitWorkManager()// 調度緩存清理任務if (shouldScheduleCleanup()) {CacheCleanerScheduler.schedule(this)}}private fun initWorkManager() {// 高級配置示例(可選)val config = Configuration.Builder().setMinimumLoggingLevel(if (BuildConfig.DEBUG) Log.DEBUG else Log.ERROR).setExecutor(Executors.newFixedThreadPool(4)).setTaskExecutor(Executors.newScheduledThreadPool(2)).build()WorkManager.initialize(this, config)}private fun shouldScheduleCleanup(): Boolean {// 實際項目中可添加更多條件判斷return !isPowerSaveMode() && hasSufficientStorage()}private fun isPowerSaveMode(): Boolean {val powerManager = getSystemService(Context.POWER_SERVICE) as PowerManagerreturn powerManager.isPowerSaveMode}private fun hasSufficientStorage(): Boolean {val stat = StatFs(cacheDir.absolutePath)val availableBytes = stat.availableBlocksLong * stat.blockSizeLongreturn availableBytes > 100 * 1024 * 1024 // 100MB以上可用空間}
}

AndroidManifest.xml配置

<applicationandroid:name=".MyApp"android:usesCleartextTraffic="true"tools:targetApi="28"><!-- WorkManager需要后臺權限 --><uses-permission android:name="android.permission.WAKE_LOCK" /><!-- 可選:添加清理任務狀態接收器 --><receiver android:name="androidx.work.impl.diagnostics.DiagnosticsReceiver"android:enabled="true"android:exported="false"tools:ignore="ExportedReceiver" />
</application>

四、高級特性與優化策略

1. 任務鏈:復雜清理流程

開始
清理圖片緩存
清理數據庫緩存
清理網絡緩存
匯總清理結果
上傳清理報告
// 創建任務鏈
fun scheduleChainedCleanup(context: Context) {val cleanImageWork = OneTimeWorkRequestBuilder<ImageCacheWorker>().build()val cleanDbWork = OneTimeWorkRequestBuilder<DbCacheWorker>().build()val cleanNetworkWork = OneTimeWorkRequestBuilder<NetworkCacheWorker>().build()val reportWork = OneTimeWorkRequestBuilder<CleanupReportWorker>().build()WorkManager.getInstance(context).beginWith(cleanImageWork).then(cleanDbWork).then(cleanNetworkWork).then(reportWork).enqueue()
}

2. 性能監控與自適應策略

class AdaptiveCacheWorker(context: Context, params: WorkerParameters) : CoroutineWorker(context, params) {override suspend fun doWork(): Result {val startTime = System.currentTimeMillis()// 獲取設備性能等級val performanceLevel = getDevicePerformanceLevel()// 根據性能調整批次大小val batchSize = when (performanceLevel) {DevicePerformance.LOW -> 20DevicePerformance.MEDIUM -> 50DevicePerformance.HIGH -> 100}// 執行自適應清理cleanCacheWithBatchSize(batchSize)// 記錄執行時間val duration = System.currentTimeMillis() - startTimesaveExecutionStats(duration, batchSize)return Result.success()}private fun getDevicePerformanceLevel(): DevicePerformance {// 根據CPU核心數、內存等判斷設備性能val cores = Runtime.getRuntime().availableProcessors()val memory = ActivityManager.MemoryInfo().let {(context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager).getMemoryInfo(it)it.totalMem / (1024 * 1024) // MB}return when {cores <= 2 && memory < 1500 -> DevicePerformance.LOWcores > 4 && memory > 3000 -> DevicePerformance.HIGHelse -> DevicePerformance.MEDIUM}}enum class DevicePerformance { LOW, MEDIUM, HIGH }
}

3. 前臺服務支持(Android 12+)

class ForegroundCacheWorker(context: Context, params: WorkerParameters) : CoroutineWorker(context, params) {override suspend fun doWork(): Result {setForeground(createForegroundInfo())return withContext(Dispatchers.IO) {// 執行長時間清理操作cleanLargeCache()Result.success()}}private fun createForegroundInfo(): ForegroundInfo {val id = NotificationHelper.NOTIFICATION_ID_CLEANUPval notification = NotificationHelper.createCleanupNotification(applicationContext)return ForegroundInfo(id, notification)}
}object NotificationHelper {const val NOTIFICATION_ID_CLEANUP = 1001fun createCleanupNotification(context: Context): Notification {val channelId = "cache_cleanup_channel"val builder = NotificationCompat.Builder(context, channelId).setContentTitle("正在優化存儲空間").setContentText("清理緩存文件中...").setSmallIcon(R.drawable.ic_cleanup).setPriority(NotificationCompat.PRIORITY_LOW)if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {val channel = NotificationChannel(channelId,"緩存清理",NotificationManager.IMPORTANCE_LOW).apply {description = "緩存清理任務通知"}val manager = context.getSystemService(NotificationManager::class.java)manager.createNotificationChannel(channel)}return builder.build()}
}

五、測試與調試策略

1. 單元測試示例

@RunWith(AndroidJUnit4::class)
class CacheCleanerWorkerTest {private lateinit var context: Contextprivate lateinit var executor: Executor@Beforefun setUp() {context = ApplicationProvider.getApplicationContext()executor = Executors.newSingleThreadExecutor()// 初始化測試WorkManagerval config = Configuration.Builder().setExecutor(executor).setTaskExecutor(executor).build()WorkManagerTestInitHelper.initializeTestWorkManager(context, config)}@Testfun testCacheCleanup() = runBlocking {// 創建測試緩存文件val testDir = File(context.cacheDir, "test_cleanup")testDir.mkdirs()repeat(10) { File(testDir, "file_$it.txt").createNewFile() }// 創建Workerval worker = CacheCleanerWorker(context, WorkerParameters.EMPTY)// 執行任務val result = worker.doWork()// 驗證結果assertThat(result, `is`(Result.success()))assertThat(testDir.listFiles()?.size, `is`(0))}@Testfun testBatchProcessing() {// 創建超過批次限制的文件val testDir = File(context.cacheDir, "large_dir")testDir.mkdirs()repeat(200) { File(testDir, "file_$it.txt").createNewFile() }val worker = CacheCleanerWorker(context, WorkerParameters.EMPTY)worker.cleanCacheDir(testDir)// 驗證批次處理val remaining = testDir.listFiles()?.size ?: 0assertThat(remaining, `is`(150)) // 200 - 50 = 150}
}

2. 調試技巧

  1. 查看任務狀態:
adb shell dumpsys jobscheduler
  1. 強制運行任務:
// 在開發模式下添加測試按鈕
fun forceRunCleanup(context: Context) {val request = OneTimeWorkRequestBuilder<CacheCleanerWorker>().build()WorkManager.getInstance(context).enqueue(request)
}
  1. 監控任務執行:
WorkManager.getInstance(context).getWorkInfoByIdLiveData(request.id).observe(this) { info ->when (info?.state) {WorkInfo.State.ENQUEUED -> println("任務排隊中")WorkInfo.State.RUNNING -> println("任務執行中")WorkInfo.State.SUCCEEDED -> println("任務成功")WorkInfo.State.FAILED -> println("任務失敗")WorkInfo.State.BLOCKED -> println("任務阻塞")WorkInfo.State.CANCELLED -> println("任務取消")}}

六、替代方案對比

方案優點缺點適用場景
WorkManager系統級調度、省電優化、任務持久化執行時間不精確定期后臺任務(推薦)
AlarmManager精確時間觸發耗電、API限制多精確時間任務(如鬧鐘)
JobScheduler系統集成度高僅支持API 21+高版本Android特定任務
Handler+Timer簡單易用應用退出后失效應用內短時任務
ForegroundService優先級高、可長時間運行需要通知、資源消耗大用戶感知的任務

七、最佳實踐總結

  1. 合理設置約束條件

    • 避免在設備資源緊張時執行
    • 優先選擇充電+空閑+WiFi場景
  2. 優化清理策略

    • 分批次處理大目錄
    • 保留近期緩存
    • 根據設備性能調整參數
  3. 完善監控體系

    • 記錄清理任務執行情況
    • 監控清理耗時和資源占用
    • 實現異常上報機制
  4. 用戶透明原則

    • 提供清理設置選項
    • 重要數據清理前確認
    • 長時間任務使用前臺服務
  5. 多場景測試

    • 低電量模式測試
    • 存儲空間不足測試
    • 設備重啟恢復測試

八、擴展思考

  1. AI驅動的智能清理

    • 基于使用習慣預測最佳清理時間
    • 根據文件重要性分級清理
    • 用戶行為分析優化保留策略
  2. 跨設備同步

    • 通過WorkManager在多設備間同步清理狀態
    • 云端統一管理清理策略
  3. 區塊鏈驗證

    • 重要清理操作上鏈存證
    • 提供不可篡改的清理記錄
  4. 隱私增強清理

    • 符合GDPR/CCPA的安全擦除
    • 軍事級文件刪除標準

提示:在實際項目中,建議結合Firebase Performance Monitoring或Sentry等工具監控清理任務性能,持續優化清理策略

通過本文的完整實現方案,你可以構建一個高效可靠的緩存清理系統,顯著提升應用性能和用戶體驗。WorkManager的強大功能結合合理的清理策略,將成為你應用維護的得力助手。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/86839.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/86839.shtml
英文地址,請注明出處:http://en.pswp.cn/web/86839.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

如何理解構件“可獨立部署”的特性

構件的“可獨立部署”特性是其區別于普通代碼模塊的核心特征之一&#xff0c;我們可以通過生活案例和技術原理解釋來理解這一特性&#xff1a; 一、生活類比&#xff1a;從“家電維修”看獨立部署 假設你家的空調壞了&#xff0c;維修時只需拆開空調外機更換壓縮機&#xff0…

uni-app subPackages 分包加載:優化應用性能的利器

&#x1f90d; 前端開發工程師、技術日更博主、已過CET6 &#x1f368; 阿珊和她的貓_CSDN博客專家、23年度博客之星前端領域TOP1 &#x1f560; 牛客高級專題作者、打造專欄《前端面試必備》 、《2024面試高頻手撕題》、《前端求職突破計劃》 &#x1f35a; 藍橋云課簽約作者、…

CentOS 8 安裝第二個jdk隔離環境

1.適用于原本已經裝了jdk8&#xff0c;現在需要安裝jdk17&#xff1a; 多版本 JDK 共存不希望修改系統默認 JavaDocker 或腳本化部署 2. 下載 Adoptium&#xff08;原 AdoptOpenJDK&#xff09; 的 OpenJDK 17&#xff1a; cd /指定目錄 sudo wget https://github.com/adopti…

Day.43

getitem方法&#xff1a; class MyList: def __init__(self): self.data [10, 20, 30, 40, 50] def __getitem__(self, idx): return self.data[idx] my_list_obj MyList() print(my_list_obj[2]) len方法&#xff1a; class MyList: def __init__(self): self.data [10…

三七互娛GO面經及參考答案

MySQL 有哪些存儲引擎?MyISAM 如何存儲數字類型數據? MySQL 擁有多種存儲引擎,每種都有其獨特的特性和適用場景。常見的存儲引擎包括 InnoDB、MyISAM、Memory、CSV、Archive、Federated 等。 InnoDB 是 MySQL 5.5 版本之后的默認存儲引擎,它支持事務、外鍵、行級鎖和崩潰恢…

git常見問題匯總-重復提交/刪除已提交文件等問題

git常見問題匯總&#xff1a; 1&#xff0c;已經commit的文件需要修改 /刪除&#xff0c;應該怎么處理&#xff1f; 2&#xff0c;自己建的分支“branch1”顯示“rebasing branch1”&#xff0c;這是什么情況&#xff1f; 3&#xff0c;由于內容修改/優化&#xff0c;在同一個…

Python實例題:簡單的 Web 服務器

目錄 Python實例題 題目 要求&#xff1a; 解題思路&#xff1a; 代碼實現&#xff1a; Python實例題 題目 簡單的 Web 服務器 要求&#xff1a; 使用 Python 的 socket 模塊實現一個簡單的 HTTP 服務器。支持以下功能&#xff1a; 處理 GET 和 POST 請求靜態文件服務…

3.Stable Diffusion WebUI本地部署和實踐

本文看了(68 封私信) 逼真的圖片生產 | Stable Diffusion WebUI本地部署看這一篇就夠了 - 知乎和(68 封私信) Stable Diffusion WebUI 實踐: 基本技法及微調 - 知乎&#xff0c;本人根據它們部署了一遍&#xff0c;中間遇到一些報錯&#xff0c;但根據報錯提示解決了問題&#…

阿里最新開源:Mnn3dAvatar 3D數字人框架, 無需聯網,本地部署可離線運行,支持多模態實時交互

Mnn3dAvatar 3D數字人框架是基于阿里巴巴開源的輕量級深度學習推理框架MNN&#xff08;Mobile Neural Network&#xff09;開發的全新3D數字人框架。Aibot親測這是一個可以在本地運行、完全離線、支持多模態實時交互的智能數字人App。可以在本地私有部署。感興趣的同學可以拿來…

03【C++ 入門基礎】函數重載

文章目錄 引言函數重載函數重載的使用函數重載的原理extern “C” 靜態多態 總結 引言 通過00【C 入門基礎】前言得知&#xff0c;C是為了解決C語言在面對大型項目的局限而誕生&#xff1a; C語言面對的現實工程問題&#xff08;復雜性、可維護性、可擴展性、安全性&#xff0…

改寫一個小項目: flask -------------------> next js

現在&#xff0c;請把上面改寫代碼的過程中&#xff0c;所有的過程&#xff0c;都寫下來&#xff0c;寫為文章的形式&#xff0c;內容比較長&#xff0c;你可以分多次輸出。而且要求語言幽默&#xff0c;苦中作樂的心態。分條理&#xff0c;要清晰。一場從 Flask 到 Next.js 的…

線性相關和線性無關

在線性代數中&#xff0c;線性相關和線性無關是刻畫向量組性質的核心概念&#xff0c;以下是關于它們的重要結論總結&#xff1a; 一、基本定義與核心判定 線性相關的定義 向量組 { α 1 , α 2 , … , α m } \{\alpha_1, \alpha_2, \dots, \alpha_m\} {α1?,α2?,…,αm?…

非常有科技感的wpf GroupBox 控件

效果 樣式 <Style TargetType="GroupBox"><Setter Property="Margin" Value="10,5" /><Setter Property="Template"><Setter.Value><ControlTemplate TargetType="GroupBox"><Grid>&l…

【Java--SQL】${}與#{}區別和危害

目錄 一區別 二SQL${}注入問題 一區別 在MyBatis中&#xff0c;#{}和${}是兩種不同的參數占位符&#xff0c;用于在SQL語句中引用變量或參數。它們的區別如下&#xff1a; 1.#{}占位符&#xff08;預編譯&#xff09;&#xff1a;#{}是MyBatis中的預編譯占位符&#xff0c;…

【科技核心期刊推薦】計算機與數字工程

【論文發表利器】《計算機技術與工程應用》——工程技術領域的學術新天地&#xff01; 作為計算機技術與工程應用交叉領域的前沿期刊&#xff0c;《計算機技術與工程應用》期刊&#xff0c;聚焦算法、系統結構、信息融合與安全、圖像處理等方向&#xff0c;為學術界提供了一個…

導出docker-compse.yml中docker鏡像成tar文件

#!/bin/bash # 確保腳本在正確的目錄下運行 SCRIPT_DIR$(dirname "$(realpath "$0")") cd "$SCRIPT_DIR" || exit 1 # 定義docker-compose文件路徑 COMPOSE_FILE"${SCRIPT_DIR}/docker-compose.yml" # 創建導出目錄 EXPORT_DIR"$…

ECMAScript 2019(ES2019):數組與對象操作的精細化升級

1.版本背景與發布 發布時間&#xff1a;2019年6月&#xff0c;由ECMA International正式發布&#xff0c;標準編號為ECMA-262 10th Edition。歷史意義&#xff1a;作為ES6之后的第四次年度更新&#xff0c;ES2019聚焦于數組、對象和字符串操作的精細化改進&#xff0c;提升開發…

2.1.1 配置堡壘機以控制Linux資產文件傳輸

文章目錄 一、試題及考試說明二、操作步驟1. 啟動JumpServer服務&#xff0c;瀏覽器登錄&#xff08;admin/Sjtu1896&#xff09;2. 創建堡壘機用戶&#xff0c;用戶名為“ops01”格式命名&#xff0c;郵箱以為“ops01jumpserver.cn”&#xff0c;使用密碼“admin123”&#xf…

react ant-design通用頁面自適應適配不同分辨率屏幕的方法工具類

該方法會根據 目標分辨率&#xff08;options.width/height&#xff09; 和 當前窗口尺寸&#xff08;innerWidth/innerHeight&#xff09; 計算縮放比例&#xff0c;并保持 等比例縮放&#xff08;Math.min(scaleX, scaleY)&#xff09;&#xff0c;確保內容不變形&#xff1a…

基于IEC61499實現的工業機器視覺方案

1.什么是機器視覺 機器視覺就是賦予機器看懂圖像的能力。它是一門涉及人工智能、計算機科學、圖像處理、光學、機械工程和自動化的交叉技術領域。核心目標是&#xff1a;通過攝像頭或其他成像設備獲取圖像或視頻&#xff0c;然后利用計算機算法對這些圖像進行分析和理解&#x…