【问题标题】:Using RxJava to return value from asynchronous call?使用 RxJava 从异步调用返回值?
【发布时间】:2019-02-08 20:16:09
【问题描述】:

好的,所以我要做的是从 firebase 收集 user_uid 的列表,然后为每个 user_uid 获取图像 url 并将其组合并返回一个对象。我遇到的问题是从异步调用中返回对象。我正在尝试实现 rxjava 来实现这一点,但我仍然得到空对象。下面我将有代码和数据库结构,这样你就可以看到我想要实现的目标,谢谢大家的帮助

这是数据库结构:

异步调用:

private Note createNoteWithArtists(Note note, ArrayList<String> user_uids) {
    DatabaseReference db_users = db_root.child("Users");
    ArrayList<User> artists = new ArrayList<>();
    Note note = note;
    for (String each_uid : user_uids) {
        db_users.child(each_uid).addListenerForSingleValueEvent(new ValueEventListener() {
            @Override
            public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
                String uid = dataSnapshot.getKey();
                String image = dataSnapshot.child("image").getValue(String.class);
                String username = dataSnapshot.child("username").getValue(String.class);
                User user = new User(username, null, image, uid);
                artists.add(user);
            }
            @Override
            public void onCancelled(@NonNull DatabaseError databaseError) {
            }
        });
    }
    note.setArtists(artists);
    return Note;
}

尝试使用 RxJava:

io.reactivex.Observable<Note> observable = io.reactivex.Observable.create(subscriber -> {
                subscriber.onNext(createNoteWithArtists(note, artists));
                subscriber.onComplete();
            });
            observable.subscribe(note -> loadNoteResults.NoteLoaded(note, true)).dispose();

它返回注释,但嵌套的艺术家对象仍然是空的:/

【问题讨论】:

    标签: java android firebase asynchronous rx-java


    【解决方案1】:

    Observable.create(...) 将在createNotWitArtists 返回值后立即发出Note。您的 RxJava 尝试在功能上等同于:

    Note emptyNote = createNoteWithArtists(note, artists);
    loadNoteResults.NoteLoaded(emptyNote , true);
    

    看看这个方法:

    private Single<User> getUser(String user_uid) {
        DatabaseReference db_users = db_root.child("Users");
        return Single.create(emitter -> {
            db_users.child(each_uid).addListenerForSingleValueEvent(new ValueEventListener() {
                @Override
                public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
                    String uid = dataSnapshot.getKey();
                    String image = dataSnapshot.child("image").getValue(String.class);
                    String username = dataSnapshot.child("username").getValue(String.class);
                    User user = new User(username, null, image, uid);
                    emitter.onSuccess(user);
                }
    
                @Override
                public void onCancelled(@NonNull DatabaseError databaseError) {
                    emitter.onError(databaseError);
                }
            });
        });
    }
    

    这个想法是使用Single.create,它会在每个onDataChange 被调用时发出。

    然后您可以像这样使用toList() 组合所有Singles:

    // Note note
    // List<String> artist
    
    Observable.fromIterable(artistIds) // Observable<String>
        .flatMapSingle(this::getUser) // Observable<User>
        .toList() // Single<List<User>>
        .subscribe( artists -> {
            note.setArtists(artists);
            loadNoteResults.NoteLoaded(note, true);
        });
    

    另外,不要忘记在需要时放置调度程序。

    【讨论】:

    • 是的,这正是我想要达到的目标!我是 Rxjava 的新手,看到这个实现对了解在哪里发生了什么以及如何使用收到的信息有很大帮助。非常感谢
    猜你喜欢
    • 2012-03-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-03
    • 1970-01-01
    • 2017-05-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多