我有一个包含用户List<User> userList
的列表。我想在列表更改时更新我的UI(从列表中删除用户或向列表添加用户)。我想在这种情况下我需要一个Observable<List<User>>
。但是我不太了解如何在RxJava中实现这一点。
如果我使用Observable<String> observable = Observable.from(userList);
,当我向userList中添加内容时会触发所有订阅者吗?
谢谢。
答案 0 :(得分:0)
如果您查看subscribe
运算符的内部,将会看到
@CheckReturnValue
@SchedulerSupport(SchedulerSupport.NONE)
public final Disposable subscribe(Consumer<? super T> onNext, Consumer<? super Throwable> onError) {
return subscribe(onNext, onError, Functions.EMPTY_ACTION, Functions.emptyConsumer());
}
因此,我们看到subscribe
得到Consumer<T>
作为参数。让我们看看吧
/**
* A functional interface (callback) that accepts a single value.
* @param <T> the value type
*/
public interface Consumer<T> {
/**
* Consume the given value.
* @param t the value
* @throws Exception on error
*/
void accept(T t) throws Exception;
}
因此,我们看到它只有一种方法:accept(T t)
。接下来,我们可以得出一个结论:Observable
订阅时,它正在等待来自消费者的事件OnNext
。因此,要触发订阅,您需要在可观察对象中调用OnNext(T T)
。但是,可观察的没有任何运算符显式地传递任何Consumer事件。但是Rx具有某种机制-Subjects
根据您的情况,最好使用 BehaviorSubject 。 Rx库还包含 AsyncSubject , PublishSubject 和 ReplaySubject 。关于它们,您可以在documentation
中阅读当观察者订阅一个BehaviorSubject时,它首先发出源Observable最近发出的项目(如果尚未发出,则为种子/默认值),然后继续发出后来由该Observable发出的任何其他项目。源可观察的。
class Test {
public static void main(String[] args) {
// creating BehaviorSubject
BehaviorSubject<String> subject = BehaviorSubject.create();
// create Observable from subject
Observable<String> observable = subject;
// subscribe to OnNext event, and when the subject will emitting some
// events, observable will print a string, receiving from subject
observable.subscribe(s -> System.out.print(s));
// sending "hello" string to observable
subject.onNext("hello");
// sending " world!" string to observable
subject.onNext(" world!");
}
}
将输出输出:
你好,世界!
让我们用List
研究您的问题。让我们定义用户类
class User {
final long id;
final String name;
public User(long id, String name) {
this.id = id;
this.name = name;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}
现在,我们有几种方法可以观察用户列表。
第一种方法是每次修改时发送观察者列表。
class Test {
public static void main(String[] args) {
// define BehaviorSubject
BehaviorSubject<List<User>> subject = BehaviorSubject.create();
// define Observable from subject
Observable<List<User>> observable = subject;
// subscribe to OnNext event, and when the subject will emitting some
// events, observable will print a string, receiving from subject
observable.subscribe(s -> System.out.println(s.toString()));
// create empty ArrayList with Users
List<User> users = new ArrayList<>();
// fill data
users.add(new User(1, "John Doe"));
users.add(new User(2, "Jane Doe"));
// send list to observable
subject.onNext(users);
// let's add one more user to list
users.add(new User(3, "Frank Doe"));
// send updated list to observable
subject.onNext(users);
}
}
将打印输出:
[User {id = 1,name ='John Doe'},User {id = 2,name ='Jane Doe'}] [User {id = 1,name ='John Doe'},User {id = 2,name ='Jane Doe'},User {id = 3,name ='Frank Doe'}]
第二种方法是对数据源进行反应式订阅。
class Test {
public static void main(String[] args) {
// create empty ArrayList with Users
List<User> users = new ArrayList<>();
// define BehaviorSubject
BehaviorSubject<User> subject = BehaviorSubject.create();
// define Observable from subject
Observable<List<User>> observable = subject.map(user -> {
users.add(user);
return users;
});
// subscribe to OnNext event
observable.subscribe(s -> System.out.println(s.toString()));
// send first user to observable
subject.onNext(new User(1, "John Doe"));
// send second user to observable
subject.onNext(new User(2, "Jane Doe"));
// send third user to observable
subject.onNext(new User(3, "Frank Doe"));
}
}
希望,我订阅的所有详细信息将帮助您使用RxJava)) 只需将代码复制粘贴到您的IDE中并进行一些实验。玩得开心!
PS 关于ConnectableObservable
,您可以在WIKI中阅读
Connectable Observable类似于普通的Observable,不同之处在于它在订阅时不会开始发出项目,而仅在调用其connect()方法时才开始发出项目。这样,您可以等待所有预期的订户订阅该Observable,然后该Observable开始发射项目。
PS 关于线程。您订阅和观察哪个线程非常重要。让我们看下一个修改的例子。
class Test {
public static void main(String[] args) {
// define BehaviorSubject
BehaviorSubject<List<User>> subject = BehaviorSubject.create();
// define Observable from subject
Observable<List<User>> observable = subject;
// subscribe to OnNext event, and when the subject will emitting some
// events, observable will print a string, receiving from subject
observable
.subscribeOn(Schedulers.io())
.observeOn(Schedulers.io())
.subscribe(s -> System.out.println(s.toString()));
// create empty ArrayList with Users
List<User> users = new ArrayList<>();
// fill data
users.add(new User(1, "John Doe"));
users.add(new User(2, "Jane Doe"));
// send list to observable
subject.onNext(users);
// let's add one more user to list
users.add(new User(3, "Frank Doe"));
// send updated list to observable
subject.onNext(users);
// it's a hack, because if delete this string output will be empty
while (true){}
}
}
在继续阅读之前尝试猜测:将输出什么输出?
输出将是:
[User {id = 1,name ='John Doe'},User {id = 2,name ='Jane Doe'},User {id = 3,name ='Frank Doe'}] [User {id = 1,name ='John Doe'},User {id = 2,name ='Jane Doe'},User {id = 3,name ='Frank Doe'}]
为什么?因为subscribeOn
和observeOn
发生在IO线程上。
subject.onNext(users);
将List<User>
的对象从主线程发送到IO,第二次调用subject.onNext(users);
时,用户列表已被修改。这是异步操作,应谨慎使用。
出于相同的原因,我们需要添加hack while (true){}
,因为Observable
已订阅了IO线程,并且主线程中的所有工作都已完成并且应用程序调用系统退出。
例如,我要添加Thread.sleep
并删除无限循环
class Test {
public static void main(String[] args) {
// define BehaviorSubject
BehaviorSubject<List<User>> subject = BehaviorSubject.create();
// define Observable from subject
Observable<List<User>> observable = subject;
// subscribe to OnNext event, and when the subject will emitting some
// events, observable will print a string, receiving from subject
observable
.subscribeOn(Schedulers.io())
.observeOn(Schedulers.io())
.subscribe(s -> System.out.println(s.toString()));
// create empty ArrayList with Users
List<User> users = new ArrayList<>();
// fill data
users.add(new User(1, "John Doe"));
users.add(new User(2, "Jane Doe"));
// send list to observable
subject.onNext(users);
// let's suspend the thread, and wait when list will receive observable
try {
Thread.sleep(1000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
// let's add one more user to list
users.add(new User(3, "Frank Doe"));
// send updated list to observable
subject.onNext(users);
}
}
现在,将输出输出:
[User {id = 1,name ='John Doe'},User {id = 2,name ='Jane Doe'}]
一秒钟后将打印第二个字符串
[User {id = 1,name ='John Doe'},User {id = 2,name ='Jane Doe'},User {id = 3,name ='Frank Doe'}]
因此,Thread.sleep
仅用于显示可观察对象和主题可以是异步的,以及它们在不同时间段内的行为。