当前位置: 首页 > article >正文

Android四大组件通讯指南:Kotlin版组件茶话会

        某日,Android王国举办Kotlin主题派对。Activity穿着Jetpack Compose定制礼服,Service戴着协程手表,BroadcastReceiver拿着Flow喇叭,ContentProvider抱着Room数据库入场。它们正愁如何交流,Intent举着"邮差"牌子跳出来:"嘿伙计们,这次我用Kotlin语法糖寄快递!"   

一、Activity:前台明星的优雅社交

        Activity作为门面担当,现在有了新绝活——用Kotlin的简洁语法处理生命周期(再也不用写冗长的onSaveInstanceState了!)

启动Activity的三种优雅姿势

// 1. 标准快递(带lambda的快递单)
startActivity(Intent(this, DetailActivity::class.java).apply {putExtra("order_id", "KT2023_888")
}// 2. 专属VIP通道(避免重复创建)
val intent = Intent(this, SingleTopActivity::class.java).apply {flags = Intent.FLAG_ACTIVITY_SINGLE_TOP
}
startActivity(intent)// 3. 协程风格带回执(等待对方签收)
val resultLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->if (result.resultCode == RESULT_OK) {result.data?.getStringExtra("result")?.let { toast("收到回信:$it")}}
}resultLauncher.launch(Intent(this, FeedbackActivity::class.java))

Kotlin参数传递魔法

// 发送方使用apply作用域函数
Intent(this, OrderActivity::class.java).apply {putExtra("order_id", "KT2023_888")putExtra("items", parcelableItemList) // 传递Parcelable集合putExtra("discount", 0.8f)
}.also { startActivity(it) }// 接收方使用kotlin扩展函数
class OrderActivity : AppCompatActivity() {private val orderId by lazy { intent.getStringExtra("order_id") ?: "" }private val discount by lazy { intent.getFloatExtra("discount", 1.0f) }private val items by lazy { intent.getParcelableArrayListExtra<Item>("items") ?: arrayListOf()}override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)// 直接使用属性访问Log.d("Order", "处理订单:$orderId 折扣:$discount")}
}

Kotlin版Intent参数速记表

操作Kotlin优雅写法
创建IntentIntent(context, Target::class.java)
添加参数apply { putExtra(key, value) }
安全获取Stringintent.getStringExtra(key) ?: ""
安全获取集合intent.getParcelableArrayListExtra<T>(key) ?: arrayListOf()
启动Activityalso { startActivity(it) }

二、Service:后台协程大师

Service现在学会用协程处理后台任务:"我再也不怕ANR了!"(但要注意:Android 12+限制前台服务启动

方式一:StartService(协程版后台任务)
// Activity发送启动命令
val serviceIntent = Intent(this, DownloadService::class.java).apply {putExtra("url", "https://example.com/kotlin_video.mp4")
}
ContextCompat.startForegroundService(this, serviceIntent)// Service使用协程处理
class DownloadService : Service() {private val job = SupervisorJob()private val scope = CoroutineScope(Dispatchers.IO + job)override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {intent?.getStringExtra("url")?.let { url ->scope.launch {downloadFile(url) // 协程中执行耗时操作stopSelf()}}return START_STICKY}private suspend fun downloadFile(url: String) {// 协程下载逻辑}override fun onDestroy() {job.cancel()super.onDestroy()}
}
方式二:BindService(Kotlin接口双向通话)
// Activity绑定服务
val connection = object : ServiceConnection {override fun onServiceConnected(name: ComponentName?, service: IBinder?) {(service as? MusicService.LocalBinder)?.getService()?.let { musicService ->musicService.apply {play() // 直接调用setOnProgressListener { progress -> updateProgress(progress) }}}}
}
bindService(Intent(this, MusicService::class.java), connection, Context.BIND_AUTO_CREATE)// Service提供Flow接口
class MusicService : Service() {private val _progress = MutableStateFlow(0)val progress: StateFlow<Int> = _progressinner class LocalBinder : Binder() {fun getService() = this@MusicService}fun play() {CoroutineScope(Dispatchers.Default).launch {while (isPlaying) {delay(1000)_progress.update { it + 1 }}}}
}

Kotlin版Service对比

特性协程优势
生命周期通过CoroutineScope管理
线程切换使用Dispatchers.IO/Main
状态更新通过StateFlow自动更新UI
错误处理协程异常处理器统一捕获

三、BroadcastReceiver:Flow化广播站

BroadcastReceiver扔掉大喇叭:"我现在用Flow收集广播,环保又高效!"

案例:协程监听网络变化
// 使用Flow包装广播
class NetworkStateFlow(context: Context) : Flow<Boolean> {private val contextRef = WeakReference(context)override suspend fun collect(collector: FlowCollector<Boolean>) {val context = contextRef.get() ?: returnval receiver = object : BroadcastReceiver() {override fun onReceive(context: Context?, intent: Intent?) {val isConnected = context?.let { ctx ->(ctx.getSystemService(CONNECTIVITY_SERVICE) as ConnectivityManager).activeNetworkInfo?.isConnected == true} ?: falsecollector.emit(isConnected)}}context.registerReceiver(receiver, IntentFilter(CONNECTIVITY_ACTION))try {awaitCancellation() // 等待流取消} finally {context.unregisterReceiver(receiver)}}
}// Activity中优雅收集
lifecycleScope.launch {NetworkStateFlow(this@MainActivity).collect { isConnected ->binding.networkStatus.text = if (isConnected) "在线" else "离线"}
}

四、ContentProvider:Room数据库管家

ContentProvider举着Room牌咖啡:"我现在用Kotlin符号查询数据,香醇又高效!"

案例:使用Room进行组件通讯
// 定义数据库
@Database(entities = [User::class], version = 1)
abstract class AppDatabase : RoomDatabase() {abstract fun userDao(): UserDao
}// DAO接口使用Kotlin协程
@Dao
interface UserDao {@Insertsuspend fun insert(user: User)@Query("SELECT * FROM user")fun getAll(): Flow<List<User>>
}// Activity中观察数据变化
class UserActivity : AppCompatActivity() {private val db by lazy {Room.databaseBuilder(applicationContext, AppDatabase::class.java, "user.db").build()}override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)lifecycleScope.launch {db.userDao().getAll().collect { users ->// 自动更新UIbinding.userList.adapter = UserAdapter(users)}}// Service更新数据Intent(this, SyncService::class.java).also { startService(it)}}
}// Service更新数据
class SyncService : Service() {private val db by lazy { Room.databaseBuilder(applicationContext, AppDatabase::class.java, "user.db").build()}override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {CoroutineScope(Dispatchers.IO).launch {val newUser = User(name = "Kotlin开发者")db.userDao().insert(newUser)}return START_NOT_STICKY}
}

组件协作实战:新闻阅读App

// 场景:Activity启动Service获取新闻,Service保存到数据库,广播通知更新,ContentProvider提供数据// 1. Activity启动服务
val serviceIntent = Intent(this, NewsService::class.java).apply {putExtra("category", "technology")
}
ContextCompat.startForegroundService(this, serviceIntent)// 2. Service获取数据并保存
class NewsService : Service() {private val db by lazy { NewsDatabase.get(applicationContext) }override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {val category = intent?.getStringExtra("category") ?: "general"CoroutineScope(Dispatchers.IO).launch {val news = NewsApi.fetch(category) // 网络请求db.newsDao().insertAll(news)// 发送粘性广播通知更新sendBroadcast(Intent("NEWS_UPDATED").apply {putExtra("count", news.size)})}return START_STICKY}
}// 3. Activity接收广播更新UI
private val receiver = object : BroadcastReceiver() {override fun onReceive(context: Context?, intent: Intent?) {if (intent?.action == "NEWS_UPDATED") {val count = intent.getIntExtra("count", 0)binding.newsCount.text = "更新了${count}条新闻"// 从ContentProvider加载数据lifecycleScope.launch {db.newsDao().getLatest().collect { news ->binding.newsList.adapter = NewsAdapter(news)}}}}
}override fun onStart() {super.onStart()registerReceiver(receiver, IntentFilter("NEWS_UPDATED"))
}

组件通讯黄金法则:Kotlin版

  1. Intent快递法则:用apply{}打包数据,用let{}安全拆包

  2. 协程管理法则:Service用CoroutineScope管理任务,Activity用lifecycleScope收集数据

  3. Flow更新法则:用StateFlow替代回调,用collect自动更新UI

  4. Room数据库法则:DAO返回Flow,实现跨组件实时同步

  5. 广播进化法则:用Flow包装传统广播,实现响应式接收

相关文章:

Android四大组件通讯指南:Kotlin版组件茶话会

某日&#xff0c;Android王国举办Kotlin主题派对。Activity穿着Jetpack Compose定制礼服&#xff0c;Service戴着协程手表&#xff0c;BroadcastReceiver拿着Flow喇叭&#xff0c;ContentProvider抱着Room数据库入场。它们正愁如何交流&#xff0c;Intent举着"邮差"牌…...

C++.OpenGL (11/64)材质(Materials)

材质(Materials) 真实感材质系统 #mermaid-svg-NjBjrmlcpHupHCFQ {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-NjBjrmlcpHupHCFQ .error-icon{fill:#552222;}#mermaid-svg-NjBjrmlcpHupHCFQ .error-text{fill:…...

AudioRelay 0.27.5 手机充当电脑音响

—————【下 载 地 址】——————— 【​本章下载一】&#xff1a;https://pan.xunlei.com/s/VOS4MvfPxrnfS2Zu_YS4egykA1?pwdi2we# 【​本章下载二】&#xff1a;https://pan.xunlei.com/s/VOS4MvfPxrnfS2Zu_YS4egykA1?pwdi2we# 【百款黑科技】&#xff1a;https://uc…...

会计 - 合并1- 业务、控制、合并日

一、业务 1.1 业务的定义以及构成要素 业务,是指企业内部某些生产经营活动或资产的组合,该组合一般具有投入、加工处理过程和产出能力,能够独立计算其成本费用或所产生的收入。 (1)投入,指原材料、人工、必要的生产技术等无形资产以及构成产出能力的机器设备等其他长期资…...

前端项目eslint配置选项详细解析

文章目录 1. 前言2、错误级别3、常用规则4、目前项目使用的.eslintrc.js 1. 前言 ‌ESLint‌ 是一个可配置的 JavaScript 代码检查工具&#xff0c;旨在帮助开发者发现并修复代码中的潜在问题&#xff0c;包括语法错误、逻辑错误以及风格不一致等问题。以下是其核心功能和特点…...

NVIDIA Dynamo:数据中心规模的分布式推理服务框架深度解析

NVIDIA Dynamo&#xff1a;数据中心规模的分布式推理服务框架深度解析 摘要 NVIDIA Dynamo是一个革命性的高吞吐量、低延迟推理框架&#xff0c;专为在多节点分布式环境中服务生成式AI和推理模型而设计。本文将深入分析Dynamo的架构设计、核心特性、代码实现以及实际应用示例&…...

第十三节:第四部分:集合框架:HashMap、LinkedHashMap、TreeMap

Map集合体系 HashMap集合的底层原理 HashMap集合底层是基于哈希表实现的 LinkedHashMap集合的底层原理 TreeMap集合的底层原理 代码&#xff1a; Student类 package com.itheima.day26_Map_impl;import java.util.Objects;public class Student implements Comparable<Stu…...

Spring AI之RAG入门

目录 1. 什么是RAG 2. RAG典型应用场景 3. RAG核心流程 3.1. 检索阶段 3.2. 生成阶段 4. 使用Spring AI实现RAG 4.1. 创建项目 4.2. 配置application.yml 4.3. 安装ElasticSearch和Kibana 4.3.1. 安装并启动ElasticSearch 4.3.2. 验证ElasticSearch是否启动成功 …...

应用案例 | 设备分布广, 现场维护难? 宏集Cogent DataHub助力分布式锅炉远程运维, 让现场变“透明”

在日本&#xff0c;能源利用与环保问题再次成为社会关注的焦点。越来越多的工业用户开始寻求更高效、可持续的方式来运营设备、管理能源。而作为一家专注于节能与自动化系统集成的企业&#xff0c;日本大阪的TESS工程公司给出了一个值得借鉴的答案。 01 锅炉远程监控难题如何破…...

C#中的密封类与静态类:特性、区别与应用实例

深入解析两类特殊类的设计哲学与实战应用 在面向对象编程领域中&#xff0c;C#提供了多种特殊的类类型以满足不同设计需求。其中密封类&#xff08;sealed class&#xff09;和静态类&#xff08;static class&#xff09;是最常用的两种特殊类类型。本文将从设计理念、应用场…...

LINUX 66 FTP 2 ;FTP被动模式;FTP客户服务系统

19&#xff0e; 在vim中将所有 abc 替换为 def&#xff0c;在底行模式下执行©&#xff1f;D A、s/abc/def B、s/abc/def/g C、%s/abc/def D、%s/abc/def/g FTP连接 用户名应该填什么 [rootcode ~]# grep -v ^# /etc/vsftpd/vsftpd.conf anonymous_enableNO local_enab…...

网心云 OEC/OECT 笔记(2) 运行RKNN程序

目录 网心云 OEC/OECT 笔记(1) 拆机刷入Armbian固件网心云 OEC/OECT 笔记(2) 运行RKNN程序 RKNN OEC/OEC-Turbo 使用的芯片是 RK3566/RK3568, 这个系列是内建神经网络处理器 NPU 的, 利用 RKNN 可以部署运行 AI 模型利用 NPU 硬件加速模型推理. 要使用 NPU, 首先需要在电脑使…...

vue-21 (使用 Vuex 模块和异步操作构建复杂应用)

实践练习:使用 Vuex 模块和异步操作构建复杂应用 Vuex 模块提供了一种结构化的方式来组织你的应用程序状态,特别是当应用程序变得复杂时。命名空间模块通过防止命名冲突和提高代码可维护性来增强这种组织。异步操作对于处理从 API 获取数据等操作至关重要,这些操作在现代 W…...

#开发环境篇:postMan可以正常调通,但是浏览器里面一直报403

本地header代理下面内容即可 headers: { // 添加必要的请求头 ‘Host’: ‘服务端域名’, ‘Origin’: https://服务端域名, ‘Referer’: https://服务端域名 }, devServer: {// 本地开发代理API地址proxy: {^/file: {target: https://服务端域名,changeOrigin: true, // 是否…...

将word文件转为kindle可识别的azw3文件的方法

亚马逊在中国停服后&#xff0c;要将word文件传送到kindle设备上进行阅读就不能通过电子邮件的方式了&#xff0c;只能通过将word文件进行转换后通过数据线传到kindle的方式来实现&#xff0c;通过线上或线下的转换工具可将word文件转化为azw文件&#xff0c;但通过数据线将转换…...

动态规划之01背包

首要 由于自己的个人原因(说白了就是懒)&#xff0c;忙于各种事情&#xff0c;实在忙不过来(哭)&#xff0c;只能把发文分享的事情一推再推&#xff0c;直到某天良心发现产生了想发文的想法&#xff0c;于是就写下了这篇文章&#xff0c;请各位大佬轻喷 背包问题 背包问题是一…...

Lua和JS的继承原理

JavaScript 和 Lua 都是动态语言&#xff0c;支持面向对象编程&#xff08;OOP&#xff09;&#xff0c;但它们的 继承机制 实现方式不一样。下面分别介绍它们的继承实现原理和方式&#xff1a; &#x1f536; JavaScript 的继承机制 JavaScript 使用的是 基于原型&#xff08…...

灵活控制,modbus tcp转ethernetip的 多功能水处理方案

油田自动化和先进的油气行业软件为油气公司带来了诸多益处。其中包括&#xff1a; 1.自动化可以消除多余的步骤、减少人为错误并降低运行设备所需的能量&#xff0c;从而降低成本。 2.油天然气行业不断追求高水平生产。自动化可以更轻松地减少计划外停机时间&#xff0c;从而…...

boost::qvm 使用示例

boost::qvm 使用示例 boost::qvm (Quaternions, Vectors and Matrices) 是 Boost 库中的一个组件&#xff0c;专门用于处理向量、矩阵和四元数运算。以下是几个常见的使用示例&#xff1a; 基本向量操作 #include <boost/qvm/vec.hpp> #include <boost/qvm/vec_ope…...

go语言学习 第6章:错误处理

第6章&#xff1a;错误处理 在任何编程语言中&#xff0c;错误处理都是一个至关重要的环节。Go语言以其简洁而强大的错误处理机制而闻名&#xff0c;这使得开发者能够以一种优雅且高效的方式处理程序中可能出现的错误情况。本章将深入探讨Go语言中的错误处理机制&#xff0c;包…...

VMware 安装 CentOS8详细教程 (附步骤截图)附连接公网、虚拟机yum源等系统配置

1 下载安装镜像 centos8官方源已下线,旧的下载地址已不可用,需要切换centos-vault源 华为云CentOS8镜像下载地址 阿里云CentOS8镜像下载地址 中科大CentOS8镜像下载地址 2 安装CentOS8 2.1 创建虚拟机 打开VMware Workstation 左上角 文件-新建虚拟机...

Editing Language Model-based Knowledge Graph Embeddings

基于语言模型的知识图谱嵌入 原文链接&#xff1a;https://arxiv.org/abs/2301.10405 Comment: AAAI 2024.03 摘要 基于语言模型的KG嵌入通常部署为静态工件&#xff0c;这使得它们在部署后如果不重新训练就很难修改。在本文中提出了一个编辑基于语言模型的 KG 嵌入的新任务。…...

深入了解linux系统—— 进程池

前言&#xff1a; 本篇博客所涉及到的代码以同步到本人gitee&#xff1a;进程池 迟来的grown/linux - 码云 - 开源中国 一、池化技术 在之前的学习中&#xff0c;多多少少都听说过池&#xff0c;例如内存池&#xff0c;线程池等等。 那这些池到底是干什么的呢&#xff1f;池…...

JavaScript 原型与原型链:深入理解 __proto__ 和 prototype 的由来与关系

引言 在 JavaScript 的世界中&#xff0c;原型和原型链是理解这门语言面向对象编程&#xff08;OOP&#xff09;机制的核心。不同于传统的基于类的语言如 Java&#xff0c;JavaScript 采用了一种独特的原型继承机制。本文将深入探讨 __proto__ 和 prototype 的由来、关系以及它…...

逻辑回归与Softmax

Softmax函数是一种将一个含任意实数的K维向量转化为另一个K维向量的函数,这个输出向量的每个元素都在(0, 1)区间内,并且所有元素之和等于1。 因此,它可以被看作是某种概率分布,常用于多分类问题中作为输出层的激活函数。这里我们以拓展逻辑回归解决多分类的角度对Softmax函…...

vscode .husky/pre-commit: line 4: npx: command not found

目录 1. 修复 npx 路径问题&#xff08;90% 的解决方案&#xff09;2. 显式加载环境变量&#xff08;nvm 用户必选&#xff09;3. 修复全局 PATH 配置4. 重装 Husky 与钩子5. 使用 HUSKY_DEBUG 调试执行流程 &#x1f527; 核心解决方法&#xff08;按优先级排序&#xff09; …...

光电耦合器:数字时代的隐形守护者

在数字化、自动化高速发展的今天&#xff0c;光电耦合器正以一种低调却不可或缺的方式&#xff0c;悄然改变着我们的生活。它不仅是电子电路中的“安全卫士”&#xff0c;更是连接信号世界的“桥梁”&#xff0c;凭借出色的电气隔离能力&#xff0c;为各类设备提供稳定可靠的信…...

FPGA没有使用的IO悬空对漏电流有没有影响

结论&#xff1a; 1.在FPGA中&#xff0c;没有使用的IO悬空确实是可能对漏电流和功耗产生一定的影响。 2.这种影响特别是在低功耗设计中或者电流敏感的应用中需要注意。 问题一&#xff1a;未连接 IO&#xff08;Floating IO&#xff09;会不会产生漏电流&#xff1f; 1.会有影…...

11. vue pinia 和react redux、jotai对比

对比 Vue 的 Pinia&#xff0c;和 React 的 Redux、Jotai&#xff0c;分中英文简要介绍、特性、底层原理、使用场景。 简单介绍 1.1 Pinia&#xff08;Vue&#xff09; • 英文&#xff1a;Pinia is the official state management library for Vue 3, designed to be simple…...

手机如何防止ip关联?3种低成本方案

在当今数字化时代&#xff0c;手机已成为人们日常生活中不可或缺的工具&#xff0c;无论是社交、购物、支付还是工作&#xff0c;都离不开手机。然而&#xff0c;随着网络技术的不断发展&#xff0c;网络安全问题也日益突出&#xff0c;其中IP关联问题尤为常见。那么&#xff0…...