在Java中,如果要监听List的内容变化,可以使用Java自带的观察者模式Observable或者第三方库(LiveData \RxJava)实现,下面分别介绍:
三者的区别优劣势、使用场景分析
下面是 Observable、LiveData、RxJava 监听 bean 对象的区别整理成表格:
特性 | Observable | LiveData | RxJava |
---|---|---|---|
生命周期 | 不受生命周期控制 | 受生命周期控制 | 受生命周期控制 |
线程安全 | 非线程安全 | 线程安全 | 非线程安全 |
广播通知 | 可使用广播通知 | 不支持广播通知 | 不支持广播通知 |
数据初始值 | 可以在任何时候发送初始值 | 只能在主线程发送初始值,启动后才有效 | 可以在任何时候发送初始值 |
语法简洁性 | 语法相对复杂 | 语法简洁 | 语法相对复杂 |
操作符 | 支持较丰富的操作符 | 不支持全部操作符 | 支持全部操作符 |
需要注意的是,在使用 RxJava 监听 bean 对象时,可以使用 ReplaySubject 或者 SerializedSubject 来实现线程安全和数据初始值的发送。同时,在 Android 开发中,建议使用 LiveData 来监听 bean 对象的变化,因为它可以很好地与 Android 生命周期进行集成,简化代码实现。
Java自带观察者模式
Java自带观察者模式中,可以使用Observable和Observer两个类实现:
a) Observable类:被观察者类,当列表发生变化时,调用其notifyObservers()方法,通知观察者。
b) Observer接口:观察者接口,当Observable发生变化时,它的update()方法将被调用。
示例代码:
import java.util.ArrayList;
import java.util.List;
import java.util.Observable;
import java.util.Observer;
public class ListObservable<T> extends Observable {
private List<T> dataList = new ArrayList<>();
public void addData(T data) {
dataList.add(data);
setChanged(); //调用setChanged()方法标记数据已经发生变化
notifyObservers(); //通知与Observable对象相关联的Observer对象
}
public List<T> getDataList() {
return dataList;
}
}
class ListObserver implements Observer {
public void update(Observable o, Object arg) {
if (o instanceof ListObservable) {
ListObservable listObservable = (ListObservable) o;
List<String> dataList = listObservable.getDataList();
System.out.println("list changed: " + dataList.toString());
}
}
}
class Main {
public static void main(String[] args) {
ListObservable<String> listObservable = new ListObservable<>();
Observer observer = new ListObserver();
listObservable.addObserver(observer);
listObservable.addData("A");
listObservable.addData("B");
}
}
在上述示例中,我们创建了一个ListObservable类来实现被观察者。当加入新的元素时,调用addData()方法更新被观察者并通知观察者。我们还创建了一个ListObserver类来实现观察者接口,在update()方法中可以获取到最新的数据并进行相应处理。
使用第三方库实现
LiveData
如果使用的是Android开发,可以使用LiveData或者RxJava来监听List的变化。以LiveData为例,示例代码如下:
public class ListLiveData<T> extends MutableLiveData<List<T>> {
private List<T> dataList = new ArrayList<>();
public void addData(T data) {
dataList.add(data);
postValue(dataList); //postValue方法可以通知观察者列表已经发生变化
}
}
class MainActivity extends AppCompatActivity {
private ListLiveData<String> data = new ListLiveData<>();
private TextView textView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
textView = findViewById(R.id.text_view);
data.observe(this, new Observer<List<String>>() {
@Override
public void onChanged(List<String> dataList) {
textView.setText(dataList.toString());
}
});
data.addData("A");
data.addData("B");
}
}
在上述示例中,我们创建了一个ListLiveData类来实现LiveData,当加入新的元素时,调用addData()方法更新LiveData并通知观察者。我们还在MainActivity中将data.observe()设置在onCreate()方法中,以便观察LiveData中的数据是否发生变化,并在观察者Observer的onChanged()方法中更新UI。
RxJava
在 RxJava 中,如果要监听 List 的内容变化,可以使用 Observable 来实现,监听内容变化的方式通常有以下几种:
- 使用 just() 方法创建 Observable,并使用 fromIterable() 方法将 List 转换为 Observable 对象,然后使用重载版本的 subscribe() 方法订阅:
List<String> dataList = new ArrayList<>();
//...
Observable<List<String>> observable = Observable.just(dataList);
observable
.flatMapIterable(list -> list) // 将 List<String> 转换为 Observable<String>
.subscribe(data -> {
// 监听 List<String> 中元素的变化
});
- 创建一个 Subject,并将订阅的 Observable 转换为 Subject,然后使用 Subject 订阅 List 中的元素:
List<String> dataList = new ArrayList<>();
//...
Subject<String> dataSubject = PublishSubject.<String>create().toSerialized();
Observable<String> dataObservable = dataSubject.filter(dataList::contains);
Observable
.just(dataList)
.flatMapIterable(list -> list) // 将 List<String> 转换为 Observable<String>
.subscribe(dataSubject);
dataObservable.subscribe(data -> {
// 监听 List<String> 中元素的变化
});
- 使用 RxRelay 库提供的 PublishRelay、BehaviorRelay 或者 ReplayRelay 来监听 List 内容的变化,可以通过直接操作 List,来实现 Relay 中数据的变化和通知:
List<String> dataList = new ArrayList<>();
//...
BehaviorRelay<List<String>> dataRelay = BehaviorRelay.createDefault(dataList);
dataRelay.subscribe(dataList1 -> {
// 监听 List<String> 中元素的变化
});
在上述示例中,我们可以通过flatMapIterable()将 List 转换为 Observable,并使用 subscribe() 监听 List 中元素的变化;通过 Subject 将订阅的 Observable 转换为 Subject,并使用 Subject 订阅 List 中的元素;通过 Relay 直接操作 List 来实现数据的变化和通知。
无论使用哪种方式,使用 RxJava 监听 List 的内容变化常用于在订阅元素的同时,实时的对 List 中的数据进行增删改的操作,同时提高了代码的可维护性和可读性。