在Android开发中,观察者模式是一种应用极为广泛的设计模式,它解决了对象间一对多的依赖关系——当一个对象(被观察者)的状态发生变化时,所有依赖它的对象(观察者)会自动收到通知并更新。这种模式能有效解耦被观察者和观察者,让系统更灵活、可扩展。
一、观察者模式的核心角色
观察者模式包含4个核心角色,它们的分工明确,共同实现“状态变化→自动通知”的逻辑:
| 角色 | 职责 |
|---|---|
| 被观察者(Observable) | 持有所有观察者的引用,提供注册、移除观察者的方法,以及状态变化时通知所有观察者的方法。 |
| 观察者(Observer) | 定义一个更新接口,当被观察者状态变化时,被观察者会调用此接口通知观察者。 |
| 具体被观察者(ConcreteObservable) | 被观察者的具体实现,维护自身状态,当状态变化时触发通知逻辑。 |
| 具体观察者(ConcreteObserver) | 观察者的具体实现,实现更新接口,在收到通知时执行具体的业务逻辑(如UI刷新、数据处理等)。 |
二、Android中的观察者模式实现
Android框架中内置了许多基于观察者模式的组件,同时开发者也可以自定义实现。
1. 基于Android原生Observable和Observer的实现(Java)
Android早期提供了java.util.Observable(被观察者基类)和java.util.Observer(观察者接口),可直接使用:
-
步骤1:定义具体被观察者
继承Observable,维护状态并在状态变化时调用setChanged()(标记状态已变)和notifyObservers()(通知所有观察者):public class WeatherData extends Observable { private float temperature; // 温度(被观察的状态) // 更新温度并通知观察者 public void setTemperature(float temp) { this.temperature = temp; setChanged(); // 标记状态已改变(必须调用,否则通知无效) notifyObservers(temp); // 通知所有观察者,可传递状态数据 } } -
步骤2:定义具体观察者
实现Observer接口,在update()方法中处理被观察者的通知:// 示例:显示温度的UI观察者 public class TemperatureDisplay implements Observer { @Override public void update(Observable o, Object arg) { if (arg instanceof Float) { float temperature = (Float) arg; // 收到温度更新,执行UI刷新(如TextView显示) Log.d("TemperatureDisplay", "当前温度:" + temperature + "℃"); } } } -
步骤3:关联观察者与被观察者
通过“注册”建立依赖关系,被观察者状态变化时,观察者自动响应:public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // 创建被观察者 WeatherData weatherData = new WeatherData(); // 创建观察者 TemperatureDisplay display = new TemperatureDisplay(); // 注册观察者 weatherData.addObserver(display); // 模拟温度变化,此时观察者会收到通知 weatherData.setTemperature(25.5f); // 输出:当前温度:25.5℃ } }
2. Android中的“观察者模式”典型应用
除了自定义实现,Android框架中大量场景基于观察者模式设计,例如:
-
ListView/RecyclerView的Adapter
当数据发生变化时,调用notifyDataSetChanged(),ListView会自动刷新UI。这里Adapter是被观察者,ListView的内部布局是观察者——数据变化→通知UI更新,本质是观察者模式的变种。 -
BroadcastReceiver(广播)
- 广播发送者(如
sendBroadcast())是被观察者; - 广播接收者(
BroadcastReceiver)是观察者,通过registerReceiver()注册,当广播发送时,接收者的onReceive()会被回调。
- 广播发送者(如
-
DataBinding双向绑定
当数据模型(ViewModel)的字段变化时,UI会自动更新;反之,UI输入变化也会同步到数据模型。这里数据模型是被观察者,UI控件是观察者,通过ObservableField等实现自动通知。 -
RxJava/RxAndroid
核心思想是“观察者订阅被观察者”,被观察者(Observable)发送事件,观察者(Observer)接收并处理,是观察者模式的高级扩展,支持线程切换、事件转换等复杂操作。
3. 自定义观察者模式(Kotlin示例)
在Kotlin中,更推荐自定义接口实现观察者模式(避免依赖Java的Observable,更灵活):
// 1. 定义观察者接口
interface Observer {
fun onUpdate(data: String) // 接收被观察者的通知,参数为状态数据
}
// 2. 定义被观察者接口
interface Observable {
fun registerObserver(observer: Observer) // 注册观察者
fun removeObserver(observer: Observer) // 移除观察者
fun notifyObservers() // 通知所有观察者
}
// 3. 具体被观察者(如新闻发布者)
class NewsPublisher : Observable {
private val observers = mutableListOf<Observer>()
private var latestNews: String = ""
fun setNews(news: String) {
this.latestNews = news
notifyObservers() // 新闻更新,通知所有观察者
}
override fun registerObserver(observer: Observer) {
observers.add(observer)
}
override fun removeObserver(observer: Observer) {
observers.remove(observer)
}
override fun notifyObservers() {
observers.forEach { it.onUpdate(latestNews) } // 逐个通知观察者
}
}
// 4. 具体观察者(如新闻读者)
class NewsReader(private val name: String) : Observer {
override fun onUpdate(data: String) {
println("$name 收到新闻:$data")
}
}
// 使用示例
fun main() {
val publisher = NewsPublisher()
val reader1 = NewsReader("读者A")
val reader2 = NewsReader("读者B")
publisher.registerObserver(reader1)
publisher.registerObserver(reader2)
publisher.setNews("Android观察者模式详解发布!")
// 输出:
// 读者A 收到新闻:Android观察者模式详解发布!
// 读者B 收到新闻:Android观察者模式详解发布!
}
三、观察者模式的优缺点
-
优点:
- 解耦被观察者和观察者:两者无需知道对方的具体实现,只需依赖接口,便于扩展(新增观察者时无需修改被观察者)。
- 支持广播通知:被观察者状态变化时,所有相关观察者都会收到通知,适合“一对多”场景。
-
缺点:
- 通知可能存在延迟:如果观察者数量过多,通知过程可能耗时,影响性能(需注意避免在主线程做耗时操作)。
- 可能导致循环依赖:若观察者和被观察者相互引用,可能引发内存泄漏(如Android中需在
onDestroy移除观察者)。
四、Android开发中的注意事项
-
避免内存泄漏:
被观察者通常持有观察者的强引用,若观察者是Activity/Fragment,需在生命周期结束前(如onDestroy)调用removeObserver(),否则被观察者会导致Activity无法被回收。 -
线程安全:
注册/移除观察者的操作需在同一线程(如主线程),或通过同步锁保证线程安全,避免并发修改观察者列表导致异常。 -
按需通知:
被观察者应仅在状态“真正变化”时通知观察者(如Java的Observable需调用setChanged()),避免无效通知浪费资源。
总结
观察者模式是Android开发中“解耦状态变化与响应逻辑”的核心模式,从基础的UI刷新到复杂的事件驱动(如RxJava),都能看到它的影子。掌握它的核心思想(“一对多依赖+自动通知”),能帮助我们设计更灵活、可维护的Android应用。

1042

被折叠的 条评论
为什么被折叠?



