Android WorkManager的概念和使用

1. WorkManager基础与核心概念

1.1 WorkManager概述

WorkManager是Android Jetpack架构组件库的核心成员,专为管理可靠的后台任务而设计。它提供了一套统一的API,用于调度需保障执行的延迟型异步任务(如数据同步、日志上传),确保任务在应用退出甚至设备重启后仍能完成。作为Android平台推荐的后台任务调度框架,WorkManager平衡了系统资源限制与任务执行可靠性,成为替代传统方案(如AlarmManager、JobScheduler)的现代化解决方案。

1.2 核心设计目标

  • 有保证的执行(Guaranteed Execution):通过SQLite数据库持久化任务信息,即使应用进程被终止或设备重启,系统也会在满足条件后重新调度任务。
  • 机会性执行(Opportunistic Execution):在设备资源充足时(如充电状态、空闲时段)立即执行任务,优化电池寿命与用户体验。
  • 跨版本兼容性:自动适配底层调度机制:
    • API ≥23:使用JobScheduler
    • API 14-22:降级为AlarmManager + BroadcastReceiver

1.3 核心优势

  • 简化多线程管理:自动处理线程调度,开发者只需关注Worker中的业务逻辑。
  • 灵活的任务链:支持顺序或并行任务组合,例如“下载→处理→上传”工作流可通过beginWith().then()链式调用实现。
  • 智能约束系统:通过Constraints.Builder设置执行条件(如仅WiFi下执行),避免无效唤醒。

1.4 典型适用场景

  • 关键数据操作:用户数据同步、数据库备份(需保障执行)。
  • 资源敏感型任务:大文件上传(需UNMETERED网络约束)、图片处理(需设备空闲)。
  • 聚合执行场景:日志批量上报(周期性任务 + 弹性窗口flexInterval)。

⚠️ 注意:WorkManager 不适用于实时性要求高的任务(如即时通讯),此类场景需改用前台服务或推送机制。其核心价值在于为可延迟但必须完成的任务提供标准化、低能耗的调度框架。

2. 基础使用​

2.1 ​添加依赖

在 build.gradle中添加依赖

dependencies {implementation "androidx.work:work-runtime-ktx:2.9.1" // KTX 扩展支持协程
}

2.2 创建 Worker 类​

继承 CoroutineWorker(推荐协程)或 Worker,重写 doWork()执行任务逻辑

class UploadWorker(context: Context, params: WorkerParameters) : CoroutineWorker(context, params) {override suspend fun doWork(): Result {val url = inputData.getString("KEY_URL") ?: return Result.failure()try {performUpload(url) // 执行耗时操作return Result.success(workDataOf("RESULT" to "Success"))} catch (e: Exception) {return Result.retry() // 失败时重试}}
}

2.3 配置 WorkRequest​

​​一次性任务​​(OneTimeWorkRequest)

val constraints = Constraints.Builder().setRequiredNetworkType(NetworkType.CONNECTED) // 需联网.setRequiresCharging(true) // 需充电.build()val uploadRequest = OneTimeWorkRequestBuilder<UploadWorker>().setInputData(workDataOf("KEY_URL" to "https://example.com")).setConstraints(constraints).setInitialDelay(10, TimeUnit.MINUTES) // 延迟启动.build()

周期性任务​​(PeriodicWorkRequest,​​最小间隔 15 分钟​​)

val syncRequest = PeriodicWorkRequestBuilder<SyncWorker>(15, TimeUnit.MINUTES).build()

2.4 提交任务​​

通过 WorkManager实例入队任务

WorkManager.getInstance(context).enqueue(uploadRequest)

3. Constraints有哪些方法 ?

以下方法都是 Constraints.Builder 类中的核心方法,用于为 WorkManager 的后台任务 (WorkRequest) 设置精确的执行条件

这些方法可以分为几大类:设备状态约束网络约束内容URI触发约束

3.1 设备状态约束 (Device State Constraints)

这类方法确保任务只在设备处于特定状态下才执行,对省电和用户体验至关重要。

3.1.1 setRequiresCharging(requiresCharging: Boolean): Builder
  • 作用:设置任务是否必须在设备充电时才能运行。
  • 参数requiresCharging - 设为 true 表示必须充电。
  • 默认值false(不要求充电)。
  • 使用场景:非常适合执行耗电量巨大的任务,例如大规模数据同步、备份或复杂的文件处理,可以避免在用户使用电池时消耗其电量。
3.1.2 setRequiresDeviceIdle(requiresDeviceIdle: Boolean): Builder
  • 作用:设置任务是否必须在设备空闲时才能运行。设备空闲通常指屏幕关闭一段时间且没有用户交互。
  • 参数requiresDeviceIdle - 设为 true 表示必须设备空闲。
  • 默认值false(不要求空闲)。
  • API 要求:需要 Android 6.0 (API 级别 23) 或更高。
  • 使用场景:用于执行非常占用 CPU 或网络资源的密集型任务,确保不会在用户 actively 使用设备时造成卡顿或干扰。

系统判定设备空闲需满足以下条件:

  • ​​屏幕关闭​​:设备未处于亮屏状态。
  • ​​无用户交互​​:用户未操作设备(如触摸、按键)持续 ​​≥30分钟​​。
  • ​​无活跃进程​​:无前台应用或高优先级服务占用资源。
3.1.3 setRequiresBatteryNotLow(requiresBatteryNotLow: Boolean): Builder
  • 作用:设置任务是否必须在设备电量充足时才能运行。系统定义的“低电量”阈值通常约为 15%。
  • 参数requiresBatteryNotLow - 设为 true 表示必须电量充足。
  • 默认值false(不要求电量充足)。
  • 使用场景:用于非紧急的后台任务,避免在用户电量紧张时雪上加霜。可以和高优先度的通知任务结合,低电量时暂停普通同步。
3.1.4 setRequiresStorageNotLow(requiresStorageNotLow: Boolean): Builder
  • 作用:设置任务是否必须在设备存储空间充足时才能运行。避免在存储空间即将耗尽时执行可能写入文件的操作。
  • 参数requiresStorageNotLow - 设为 true 表示必须存储空间充足。
  • 默认值false(不要求存储空间充足)。
  • 使用场景:任何需要下载文件或缓存数据的任务,如下载更新、保存图片或日志文件等。

3.2 网络约束 (Network Constraints)

这类方法控制任务执行所需的网络环境。

3.2.1 setRequiredNetworkType(networkType: NetworkType): Builder
  • 作用:设置任务执行所需的基本网络类型。这是最常用的网络约束方法。
  • 参数networkType - 枚举值,包括:
    • NOT_REQUIRED:不需要网络(默认值)。
    • CONNECTED:设备有任何网络连接即可(Wi-Fi 或移动数据)。
    • UNMETERED:需要不计流量的网络(如 Wi-Fi)。
    • METERED:需要按流量计费的网络(如移动数据)。
    • NOT_ROAMING:需要非漫游网络。
  • 使用场景
    • UNMETERED:用于下载大文件、更新应用、上传日志等大量数据传输操作。
    • CONNECTED:用于轻量级的网络请求,如发送即时消息、获取小型配置更新等。
    • METERED:用于需要明确使用移动数据的场景。
3.2.2 setRequiredNetworkRequest(networkRequest: NetworkRequest, networkType: NetworkType): Builder
  • 作用:提供一个更高级、更精细的网络约束方式(基于 Android 的 NetworkRequest API)。它允许你指定更复杂的网络能力要求,例如带宽、延迟等。在较新的 Android 版本(API 28+)上使用此设置,在旧版本上会自动回退到您指定的 networkType
  • 限制:不支持设置了 NetworkSpecifier(如指定特定 Wi-Fi SSID)或 setIncludeOtherUidNetworks 的请求,传入此类请求会抛出 IllegalArgumentException
  • API 要求:需要 Android 5.0 (API 级别 21) 或更高,但其高级功能在更高版本上才有效。
  • 使用场景:需要非常特定网络条件的专业应用,例如视频会议应用需要高上行带宽的网络,或游戏需要低延迟网络。

3.3 内容URI触发约束 (Content URI Triggers)

这是一组非常强大的约束,允许任务在你关注的特定数据发生变化时被触发,类似于数据库的触发器。

3.3.1 addContentUriTrigger(uri: Uri, triggerForDescendants: Boolean): Builder
  • 作用:添加一个要监听的内容提供者 (ContentProvider) 的 URI。当此 URI 代表的数据发生变化(插入、更新、删除)时,会触发任务运行。
  • 参数
    • uri:要监听的内容 URI(例如 content://media/external/images/media)。
    • triggerForDescendants:如果为 true,则监听该 URI 及其所有子路径的变化;如果为 false,则只监听该精确 URI。
  • API 要求:需要 Android 7.0 (API 级别 24) 或更高。
  • 使用场景
    • 监听媒体库的变化,当有新图片或视频时执行某些处理。
    • 监听自定义 ContentProvider 的数据变化,实现数据驱动型的任务调度。
3.3.2 setTriggerContentUpdateDelay(…) 与 setTriggerContentMaxDelay(…)
  • 作用:这两个方法用于控制触发延迟,以避免在数据频繁变化时任务被过于频繁地触发。
    • setTriggerContentUpdateDelay:设置从检测到内容变化调度任务之间的最小等待时间。如果在此期间内容再次变化,计时器会重置。
    • setTriggerContentMaxDelay:设置从第一次检测到内容变化调度任务之间的最大等待时间。即使内容一直在变化,超过此时间后任务也一定会被调度。
  • 重载方法:两者都提供了接受 (Long, TimeUnit)(Duration) 参数的方法,后者是更现代的 Java Time API。
  • API 要求:需要 Android 7.0 (API 级别 24) 或更高。
  • 使用场景:例如,一个文档管理应用在用户批量删除文件时,文件变化事件会连续触发。设置一个最大延迟(如 1 分钟),可以确保任务最终会执行一次以处理所有更改,而不是为每个文件的删除都执行一次。

4. CoroutineWorker和Worker的区别

CoroutineWorkerWorker 是两种核心的任务执行基类,它们的设计目标、实现机制和适用场景存在显著差异。

4.11 基础架构与线程模型

  • Worker
    基于 Java 的线程池和回调机制。其 doWork() 方法在后台线程中同步执行,需避免阻塞主线程。若任务耗时较长,可能占用线程池资源,影响其他任务调度。
  • CoroutineWorker
    基于 Kotlin 协程实现。doWork() 是挂起函数(suspend),在协程作用域内异步执行。任务可被挂起(如等待 I/O 操作),释放底层线程供其他任务使用,显著提升资源利用率。

4.2 资源消耗与并发能力

  • Worker
    每个任务独占一个线程,大量并发任务时需创建多个线程,消耗较多内存(每个线程约 1MB 栈空间)。线程切换开销在高并发场景下可能成为瓶颈。
  • CoroutineWorker
    协程轻量级(内存占用约数十 KB),单线程可调度数万协程。适合高并发 I/O 操作(如网络请求、数据库读写),避免线程资源浪费。

4.3 CoroutineWorker和Worker的doWork方法中,需要单独启动一个IO线程再执行吗 ?

4.3.1 ​​Worker(传统 Java 线程模型)​

无需额外启动 IO 线程​​:

Worker.doWork()​​默认在 WorkManager 管理的后台线程池中执行​​(非主线程)。该线程池由 Executor实现,默认大小为 2-4 个线程(基于设备 CPU 核心数)

class MyWorker(context: Context, params: WorkerParameters) : Worker(context, params) {override fun doWork(): Result {// 直接执行同步 I/O 操作(已在后台线程)val data = downloadFileSync("https://example.com/data")return Result.success()}
}
4.3.2 ​​CoroutineWorker(协程模型)​

​​无需额外启动线程,但需指定调度器​​:

CoroutineWorker.doWork()是挂起函数,​​默认运行在 Dispatchers.Default​​(计算密集型线程池)。若需 I/O 操作(如网络请求、文件读写),应使用 withContext(Dispatchers.IO)切换到 I/O 调度器。

class MyCoroutineWorker(context: Context, params: WorkerParameters) : CoroutineWorker(context, params) {override suspend fun doWork(): Result {// 切换到 IO 调度器执行阻塞操作val data = withContext(Dispatchers.IO) { downloadFile("https://example.com/data")}return Result.success()}
}

从技术趋势看,CoroutineWorker 代表了 Android 异步任务的未来方向,尤其在资源利用率和代码可维护性上优势明显。

5. PeriodicWorkRequestBuilder和OneTimeWorkRequestBuilder的区别

PeriodicWorkRequestBuilderOneTimeWorkRequestBuilder 是定义后台任务的两类核心构建器,它们的主要区别在于任务执行模式的设计目标。以下是二者的详细对比及 WorkManager 中的其他构建器类型说明:


5.1 核心区别:执行模式

特性OneTimeWorkRequestBuilderPeriodicWorkRequestBuilder
任务类型一次性任务(执行后终止)周期性任务(按固定间隔重复执行)
最小执行间隔无限制≥15分钟(受系统强制限制)
适用场景单次数据上传、即时操作处理定期数据同步、日志备份、周期检查
灵活性支持复杂约束链(如任务链 beginWith().then()仅支持独立任务(不可链式调用)
延迟配置支持精确延迟(如 setInitialDelay(10, MINUTES)仅支持重复间隔(repeatInterval)和弹性窗口(flexInterval

⚠️ 周期性任务注意事项

  • 若周期任务执行时约束未满足(如无网络),系统会跳过本次执行,不会自动补偿,需等待下一周期。
  • 弹性窗口(flexInterval)允许任务在周期末尾的弹性时段内执行(如最后15分钟),优化资源调度。

5.2 高级配置差异

  1. 重试策略

    • OneTimeWorkRequestBuilder:可通过 setBackoffCriteria() 配置指数退避策略(如失败后延迟重试)。
    • PeriodicWorkRequestBuilder不支持重试策略,失败后需等待下一周期。
  2. 加速任务(Expedited Work)

    • OneTimeWorkRequestBuilder 支持 setExpedited(),用于紧急任务(如支付操作),系统会优先分配资源。
    • 周期性任务无法加速执行。

5.3 OneTimeWorkRequestBuilder怎么使用

val constraints = Constraints.Builder().build()val workRequest = OneTimeWorkRequestBuilder<MyWorker>().setConstraints(constraints).setInitialDelay(15, TimeUnit.MINUTES) //任务延迟启动(例如 15 分钟后).setBackoffCriteria( //配置失败后的指数退避重试BackoffPolicy.EXPONENTIAL, // 或 LINEAROneTimeWorkRequest.MIN_BACKOFF_MILLIS, // 最小延迟 10 秒TimeUnit.MILLISECONDS).setExpedited(OutOfQuotaPolicy.RUN_AS_NON_EXPEDITED_WORK_REQUEST) //加急任务.build()
5.3.1 setBackoffCriteria中EXPONENTIAL和LINEAR的区别

​​EXPONENTIAL(指数退避)​​ 和 ​​LINEAR(线性退避)​​ 是两种不同的重试延迟策略,用于控制任务失败后重新调度的等待时间增长方式。

  • LINEAR​ : ​延迟时间按​​固定值线性增加​​:延迟时间 = 初始延迟 × 重试次数
  • EXPONENTIAL : 延迟时间按​​指数倍数增长 : 延迟时间 = 初始延迟 × 2^(重试次数-1)
5.3.2 setExpedited
  • RUN_AS_NON_EXPEDITED_WORK_REQUEST
    • 配额足够时​​:
      • 任务作为加急任务​​立即执行​​,享受高优先级调度(低延迟、抗省电限制)。
    • ​​配额不足时​​:
      • 任务​​自动降级为普通后台任务​​,按标准 WorkRequest流程执行:
      • 需等待约束条件满足(如联网、充电)。
      • 可能延迟执行(无加急优先级)
  • DROP_WORK_REQUEST​​
    • 配合足够时 :
      • 任务作为加急任务​​立即执行​​,享受高优先级调度(低延迟、抗省电限制)。
    • 配额不足时​​直接丢弃任务​​,不会转为普通任务

加急任务(RUN_AS_NON_EXPEDITED_WORK_REQUEST)的优先级高于延迟设置​​(setInitialDelay)
加急任务会尝试​​立即执行​​,仅受系统配额限制(如设备资源紧张时可能延迟)
若当前配额充足(如应用在前台或系统负载低),加急任务会忽略延迟时间直接启动

6. WorkManager怎么取消任务

取消任务需根据任务标识类型选择对应方法

6.1 通过任务 ID 取消

每个 WorkRequest 创建时自动生成唯一 ID (UUID),适用于精确取消单个任务。

val workRequest = OneTimeWorkRequestBuilder<MyWorker>().build()
WorkManager.getInstance(context).enqueue(workRequest)// 取消任务
WorkManager.getInstance(context).cancelWorkById(workRequest.id)

适用场景:明确知道目标任务的 ID 时使用。

6.2 通过标签 (Tag) 取消

为任务添加标签后,可批量取消同标签的所有任务:

val workRequest = OneTimeWorkRequestBuilder<MyWorker>().addTag("data_sync") // 添加标签.build()// 取消所有带此标签的任务
WorkManager.getInstance(context).cancelAllWorkByTag("data_sync")

优势:适用于逻辑分组任务(如“所有数据同步任务”)。


6.3 取消唯一任务 (Unique Work)

唯一任务通过名称 (uniqueWorkName) 标识,同一名称仅允许一个实例运行:

val workRequest = OneTimeWorkRequestBuilder<MyWorker>().build()// 提交唯一任务
WorkManager.getInstance(context).enqueueUniqueWork("unique_sync_task", ExistingWorkPolicy.REPLACE, workRequest
)// 通过唯一名称取消
WorkManager.getInstance(context).cancelUniqueWork("unique_sync_task")

策略说明

  • ExistingWorkPolicy.REPLACE:新任务自动取消旧任务。
  • 适用于防重复任务(如定时数据同步)。

6.4 取消所有任务

清理整个 WorkManager 队列:

WorkManager.getInstance(context).cancelAllWork()

慎用:会取消所有未完成的任务(包括周期任务)。


6.5 取消后的任务行为

  • 状态变更:任务状态变为 CANCELLED,但 doWork() 中的代码不会立即停止
  • 资源释放:需在 Worker 中主动检查取消信号:
    class MyWorker(context: Context, params: WorkerParameters) : Worker(context, params) {override fun doWork(): Result {while (!isStopped) { // 循环中检查取消状态// 执行逻辑}return Result.success()}override fun onStopped() {super.onStopped()// 释放资源(如关闭数据库连接)}
    }
    
    关键点
    • isStopped:检测任务是否被取消。
    • onStopped():收到取消信号时回调,用于清理资源。
6.5.1 通过workManager.getWorkInfosByTag,怎么判断是否有某个Work还未执行 ?
val workManager = WorkManager.getInstance(context)
val tag = "YOUR_TAG" // 替换为实际标签// 异步监听方式(推荐)
workManager.getWorkInfosByTagLiveData(tag).observe(this) { workInfos ->val hasUnfinishedWork = workInfos.any { workInfo ->workInfo.state == WorkInfo.State.ENQUEUED || workInfo.state == WorkInfo.State.BLOCKED}if (hasUnfinishedWork) {Log.d("WorkStatus", "存在未执行的任务")}
}// 同步查询方式(需在后台线程执行)
val workInfos = workManager.getWorkInfosByTag(tag).get()
val unfinishedWorkExists = workInfos.any { workInfo ->workInfo.state == WorkInfo.State.ENQUEUED || workInfo.state == WorkInfo.State.BLOCKED
}

6. 更多内容

有关Doze低功耗模式下的WorkManager,详见 : Android Doze低电耗休眠模式 与 WorkManager

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/web/96832.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/96832.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

容器使用卷

1.创建一个卷并让容器挂载该卷1.创建一个卷[roothost1 ~]# docker volume create test-vol test-vol2.列出本地 Docker 主机上的卷[roothost1 ~]# docker volume ls DRIVER VOLUME NAME local test-vol3.查看该卷的详细信息[roothost1 ~]# docker volume inspect test-v…

高数基础知识(下)②

文章目录七、微分方程7.3 高阶线性微分方程7.3.1 线性微分方程的解的结构7.3.2 常系数齐次线性微分方程7.3.3 常系数非齐次线性微分方程八、多元函数微分学8.1 偏导数8.2 全微分8.3 基本定理8.4 复合函数微分法8.5 隐函数微分法8.6 多元函数的极值8.6.1 无条件极值8.6.2 条件极…

从0°到180°,STM32玩转MG996R舵机

1.MG996R舵机的性能参数参数数值产品型号MG995/MG996R产品重量55 g工作扭矩13 kgcm反应速度53-62 R/M使用温度-30C ~ 55C死区设置4 微秒插头类型JR、FUTABA 通用转动角度180&#xff08;左90&#xff0c;右90&#xff09;舵机类型数码舵机使用电压3.0 - 7.2 V工作电流100 mA结构…

[frontend]mermaid code2image

hello everyone, welcome to my bolg, here i will introduce something interesting, and if you are interested it, please just let me know. follow me and send me a message are both avaiable. what is mermaid? Mermaid 是一个工具&#xff0c;它能让你用简单的文字代…

Jakarta EE 在 IntelliJ IDEA 中开发简单留言板应用的实验指导(附完整代码)

Jakarta EE 在 IntelliJ IDEA 中开发简单留言板应用的实验指导(附完整代码) 摘要:实验基于Jakarta EE 9+(兼容Tomcat 10+)、Maven作为构建工具,并在IntelliJ IDEA 2023.2(Community版免费)中进行。项目使用Maven Archetype WebApp模板生成基础结构,然后升级到J…

JavaScript经典面试题一(JavaScript基础)

目录 一、JavaScript中的变量提升 1. 机制 2. 示例 3. 注意事项 4. 总结 二、var、let和const的区别。 1. 作用域&#xff08;Scope&#xff09; 2. 变量提升&#xff08;Hoisting&#xff09; 3. 重新赋值和重新声明 4. 示例 示例1&#xff1a;作用域和块级行为 示…

数据库造神计划第七天---增删改查(CRUD)(3)

&#x1f525;个人主页&#xff1a;寻星探路 &#x1f3ac;作者简介&#xff1a;Java研发方向学习者 &#x1f4d6;个人专栏&#xff1a;《从青铜到王者&#xff0c;就差这讲数据结构&#xff01;&#xff01;&#xff01;》、 《JAVA&#xff08;SE&#xff09;----如此简单&a…

AWS SQS 可观测性最佳实践

AWS SQS AWS SQS&#xff08;Amazon Simple Queue Service&#xff09;是一种完全托管的消息队列服务&#xff0c;用于在分布式系统中解耦和缓冲消息。它支持高可用性、可扩展性和安全性&#xff0c;能够处理大量消息&#xff0c;确保消息的可靠传输和顺序性。开发者可以轻松集…

AI推理范式:从CoT到ReAct再到ToT的进化之路

在人工智能领域&#xff0c;如何让模型像人类一样进行复杂推理和问题解决&#xff0c;一直是核心挑战。近年来&#xff0c;思维链&#xff08;Chain-of-Thought, CoT&#xff09;、推理与行动&#xff08;ReAct&#xff09; 和 思维树&#xff08;Tree-of-Thoughts, ToT&#x…

2025时序数据库选型:深入解析IoTDB从主从架构基因到AI赋能的创新之路

原创经验总结,拒绝空谈,用数据和实战说话 时序数据时代的"四重考验" 在智慧工厂、新能源车、金融市场等场景中,每秒百万级的数据点如潮水般涌来。这些时序数据背后隐藏着四大核心挑战:极高的写入并发、强时间关联性查询、海量数据生命周期管理,以及乱序与高基…

深入浅出LVS负载均衡群集:原理、分类与NAT模式实战部署

深入浅出LVS负载均衡群集&#xff1a;原理、分类与NAT模式实战部署 文章目录深入浅出LVS负载均衡群集&#xff1a;原理、分类与NAT模式实战部署一、企业群集&#xff1a;从单台服务器到分布式架构的必然选择1. 什么是群集&#xff1f;2. 为什么需要群集&#xff1f;二、企业群集…

Flash Table实测:JAI赋能低代码开发,重塑企业级应用构建范式

目录&#x1f50d; 引言1.1 什么是Flash Table1.2 低代码平台的进化与FlashTable的革新✨FlashTable背景&#xff1a;为什么需要新一代低代码平台&#xff1f;2.1 传统开发的痛点2.2 低代码平台的局限2.3 FlashTable的差异化定位&#x1f4bb; FlashTable安装&#xff1a;Docke…

SonarQube代码质量管理平台本地化搭建和使用

SonarQube 是一个开源的代码质量管理平台&#xff0c;主要用于持续检查代码质量&#xff0c;支持多种编程语言。 本文章记录了在windows环境中&#xff0c;搭建和使用SonarQube的完整过程。 ①SonarQube平台搭建 SonarQube最新社区版本下载地址&#xff1a; https://www.son…

基于双向LSTM深度学习网络模型的文本序列推荐系统matlab仿真

目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.部分程序 4.算法理论概述 5.完整程序 1.程序功能描述 在信息爆炸的时代&#xff0c;用户面临着海量文本信息的筛选难题&#xff0c;文本序列推荐系统应运而生。双向长短期记忆网络&#xff08;Bi-directional Long …

Transformer实战(17)——微调Transformer语言模型进行多标签文本分类

Transformer实战(17)——微调Transformer语言模型进行多标签文本分类 0. 前言 1. 多标签文本分类 2. 数据加载与处理 3. 模型微调 小结 系列链接 0. 前言 与单标签分类不同,多标签分类要求模型能够为同一文本分配多个相关标签,这在新闻分类、文献标注、内容推荐等场景中尤…

开源 C++ QT Widget 开发(十六)程序发布

文章的目的为了记录使用C 进行QT Widget 开发学习的经历。临时学习&#xff0c;完成app的开发。开发流程和要点有些记忆模糊&#xff0c;赶紧记录&#xff0c;防止忘记。 相关链接&#xff1a; 开源 C QT Widget 开发&#xff08;一&#xff09;工程文件结构-CSDN博客 开源…

MATLAB2-结构化编程和自定义函数-台大郭彦甫视频

目录 if elseif else switch case otherwise while exercise练习 for 预宣告 练习题 break tips编程的小技巧 functions函数 练习题 函数句柄 if elseif else 如果condition为真&#xff0c;执行语句 if condition1statement1 elseif condition2statement2 elsest…

LVGL移植2048小游戏全攻略

目录 准备脚手架 修改源码 对接触摸 测试编译 测试运行 这一节将以一个已经编写好的 lvgl 小游戏 2048 描述如何将已经编写完成的 lvgl 程序移植到开发板上。 准备脚手架 在这之前&#xff0c;我们先准备基础的 LVGL 脚手架。可以直接从 lv_g2d_test 里复制过来进行修改…

在Unity2021中使用Profiler的Deep Profile功能时内存超高怎么办?

这通常是因为Deep Profile会记录每一帧所有函数调用的详细信息&#xff0c;导致内存急剧增长&#xff0c;尤其在大型项目或复杂场景中4。别担心&#xff0c;我来帮你分析原因并提供一些解决办法。 理解 Deep Profile 的内存开销与替代方案 Deep Profile是Unity Profiler的一个…

Ubuntu 设置中文输入法

一、使用 IBus&#xff08;Ubuntu 默认框架&#xff09;步骤 1&#xff1a;安装中文输入法sudo apt install ibus-libpinyin ibus-pinyin步骤 2&#xff1a;添加输入法打开 Settings > Keyboard > Input Sources。点击 “”&#xff0c;搜索 Chinese (Intelligent Pinyin…