0%

安卓多种通知ui更新的方式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
安卓多种通知 UI 的实现方式

在安卓开发中,我们经常需要在数据发生变化时通知 UI 更新,例如列表数据变化、状态改变、网络请求结果等。不同的项目架构、技术栈和团队习惯会导致选择不同的通知机制。本文整理了安卓常用的通知 UI 的方式,并分析其原理、优缺点和使用场景。

1. LiveData(Jetpack 组件)
特点

LiveData 是 Jetpack 架构组件的一部分。

具有生命周期感知(Lifecycle-aware),只在 Activity 或 Fragment 活跃时才更新 UI。

支持单向数据流,数据源更新,观察者自动收到通知。

用法示例
// ViewModel
val userName = MutableLiveData<String>()

// Activity/Fragment
viewModel.userName.observe(this) { name ->
textView.text = name
}

优点

生命周期感知,避免内存泄漏。

与 MVVM 架构自然结合。

简单易用,官方推荐。

缺点

只能在主线程更新(虽然可以用 postValue 跨线程,但有延迟)。

单向数据流,复杂事件管理可能不方便。

2. StateFlow / SharedFlow(Kotlin Coroutines)
特点

Kotlin 协程的 Flow 变体,用于响应式数据流。

StateFlow 持有最新状态,SharedFlow 用于事件流(类似 RxJava 的 PublishSubject)。

支持冷流、热流,灵活结合协程和生命周期。

用法示例
// ViewModel
private val _count = MutableStateFlow(0)
val count: StateFlow<Int> = _count

fun increment() {
_count.value += 1
}

// Fragment
lifecycleScope.launch {
viewModel.count.collect { value ->
textView.text = value.toString()
}
}

优点

与协程天然结合,异步友好。

可以处理复杂事件和状态流。

支持缓存最新值(StateFlow)。

缺点

使用前需要熟悉协程。

Lifecycle-aware 需要手动配合 lifecycleScope。

3. RxJava / RxKotlin(响应式编程)
特点

响应式流库,可实现复杂的事件组合、转换和过滤。

支持多线程切换、链式操作。

用法示例
val subject = PublishSubject.create<String>()

// 订阅
subject.observeOn(AndroidSchedulers.mainThread())
.subscribe { value -> textView.text = value }

// 发布
subject.onNext("Hello RxJava")

优点

功能强大,适合复杂事件流处理。

可实现跨组件通知。

支持背压、线程调度等高级特性。

缺点

学习成本较高。

容易产生内存泄漏,需要 CompositeDisposable 管理。

项目依赖大,现代 Android 官方更推荐使用 Flow/LiveData。

4. EventBus / Otto(事件总线)
特点

基于发布-订阅模式,实现跨组件消息传递。

组件之间无需直接引用。

用法示例(GreenRobot EventBus)
// 定义事件
data class MessageEvent(val message: String)

// 注册和接收
@Subscribe(threadMode = ThreadMode.MAIN)
fun onMessageEvent(event: MessageEvent) {
textView.text = event.message
}

// 发布事件
EventBus.getDefault().post(MessageEvent("Hello EventBus"))

优点

跨组件通信方便。

简化复杂 UI 回调链。

支持线程切换。

缺点

容易滥用,变成“全局状态管理”。

难以追踪调用链,调试困难。

生命周期管理需要手动处理注册/注销。

5. 接口回调(Callback / Listener)
特点

最传统的方式,通过接口实现组件间通信。

常用于 Adapter -> Activity / Fragment 更新 UI。

用法示例
interface OnItemClickListener {
fun onClick(position: Int)
}

adapter.setOnItemClickListener(object : OnItemClickListener {
override fun onClick(position: Int) {
textView.text = "Clicked $position"
}
})

优点

简单直接,无需依赖库。

适合局部通信。

缺点

不适合复杂跨组件通信。

易产生内存泄漏(尤其是匿名内部类持有 Activity)。

6. Handler / Message / Looper(线程间通信)
特点

Android 原生机制,用于线程间消息通知。

UI 线程通过 Handler 接收子线程消息更新 UI。

用法示例
val handler = Handler(Looper.getMainLooper()) { msg ->
textView.text = msg.obj as String
true
}

// 子线程发送消息
Thread {
val msg = Message.obtain()
msg.obj = "Hello Handler"
handler.sendMessage(msg)
}.start()

优点

精确控制线程。

官方原生,无第三方依赖。

缺点

代码繁琐,不适合复杂数据流。

与现代架构(MVVM / Jetpack)结合较差。

7. ContentProvider / LiveData + Room(数据库驱动 UI 更新)
特点

数据库变化触发 UI 更新。

Room + LiveData 可自动通知观察者。

用法示例
@Dao
interface UserDao {
@Query("SELECT * FROM user")
fun getAllUsers(): LiveData<List<User>>
}

优点

数据和 UI 双向绑定。

可实现持久化与实时更新结合。

缺点

适合持久化数据,不适合临时事件。

依赖 Room 和 LiveData。

8. BroadcastReceiver(系统广播或自定义广播)
特点

通过广播机制通知多个组件。

可以是系统广播或自定义广播。

用法示例
// 注册广播
val filter = IntentFilter("com.example.ACTION_UPDATE")
registerReceiver(receiver, filter)

// 发送广播
val intent = Intent("com.example.ACTION_UPDATE")
sendBroadcast(intent)

优点

可跨 App 或跨组件通知。

系统级事件监听。

缺点

性能开销大,不适合高频事件。

生命周期管理需要注意。

9. 总结对比表
| 方式 | 生命周期感知 | 跨组件 | 异步支持 | 使用场景 |
|--------------------------|-------------------|----------------|---------------|---------------------------|
| LiveData | ✅ | ❌ | 主线程 | MVVM UI 更新 |
| StateFlow / SharedFlow | ⚠️ 手动管理 | ✅ | ✅ 协程 | 复杂状态流 |
| RxJava | ❌ | ✅ | ✅ | 复杂事件流 / 跨组件 |
| EventBus | ❌ | ✅ | ✅ | 简单跨组件事件 |
| Callback / Listener | ❌ | ❌ | ⚠️ | 局部回调 |
| Handler / Message | ❌ | ❌ | ✅ | 子线程 -> UI |
| Room + LiveData | ✅ | ⚠️ | ✅ | 数据库驱动 UI |
| BroadcastReceiver | ❌ | ✅ | ⚠️ | 系统或跨组件事件 |