使用Android/Firebase实时数据库时,Single.Create()... blockingGet()在RxJava 2.1.3中挂起 [英] Single.Create()...blockingGet() hangs in RxJava 2.1.3 when using Android/Firebase Realtime Database

查看:565
本文介绍了使用Android/Firebase实时数据库时,Single.Create()... blockingGet()在RxJava 2.1.3中挂起的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用以下模式从Firebase实时数据库同步获取数据时:

When using the following pattern to synchronously get data from Firebase Realtime Database:

String s = Single.create(new SingleOnSubscribe<String>() {
    @Override
    public void subscribe(SingleEmitter<String> e) throws Exception {
    FirebaseDatabase.getInstance().getReference("path").orderByChild("child").equalTo("xyz").addListenerForSingleValueEvent(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
        e.onSuccess("Got it");
        }
        @Override
        public void onCancelled(DatabaseError databaseError) {
        e.onError(databaseError.toException());
        }
    });
}
}).blockingGet();

它将挂起并创建ANR错误.如果我在Single之外使用相同的Firebase内脏",则可以正常触发.内含Firebase代码的Single也会触发,因此两者似乎有些不兼容.

It will hang and create an ANR error. If I use the same Firebase "innards" outside of the Single, it fires just fine. The Single without the Firebase code inside also will fire, so it seems there is some incompatibility between the two.

有什么想法吗?

推荐答案

由于要创建自己的Single,因此应在subscribeWith中使用DisposableSingleObserver.其次,您不应该那样调用blockingGet().原因是默认情况下,您创建的Single or any observable/Processor/Flowable将被订阅(在主线程上运行其操作)并在主线程上进行观察. BlockingGet()导致mainThread暂停.就像在主线程上执行Thread.sleep()一样.这总是以灾难告终.

Since you are creating your own Single, You should use DisposableSingleObserver in subscribeWith. Secondly, you shouldn't be calling blockingGet() like that. The reason is by default the Single or any observable/Processor/Flowable you create will be subscribed (run its operations on main thread) and observe on main thread. BlockingGet() causes the mainThread to pause. It's like executing Thread.sleep() on Main Thread. This always ends in a disaster.

对您而言,最好的选择是重新考虑要在代码中放入的逻辑.由于Firebase操作本质上是异步的,因此您应该使代码适应异步模式.

The best option for you would be to rethink the logic you are trying to put in to the code. Since the Firebase operations are Async by nature, you should adapt your code to async pattern.

无论如何,您都可以执行以下操作来实现您可能想尝试执行的操作.请注意,我在此处编写了以下代码,因此可能会出现语法错误.

Anyways you can do something like the following to achieve what seems likes you might be trying to do. Note that I wrote the following code here so it might have syntactical errors.

   Single.create(new SingleOnSubscribe<String>() {
        // your firebase code
    @Override
        public void subscribe(SingleEmitter<String> e) throws Exception {

  FirebaseDatabase.getInstance().getReference("path").orderByChild("child").equalTo("xyz").addListenerForSingleValueEvent(new ValueEventListener() {
            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {
            e.onSuccess("My String");
            }
            @Override
            public void onCancelled(DatabaseError databaseError) {
            e.onError(databaseError.toException());
            }
        });
       }
    })
    .subscribeOn(Schedular.io())
    .observeOn(AndroidThread.mainThread()) // if you aren't doing intensive/long running tasks on the data you got from firebase
    .subscribeWith(new DisposableSingleObserver<String>() { 
         public void onSuccess(String myString) {
               mMyString = myString;
         }
         public void onError(Throwable t) {
            Timber.e("error in fetching data from firebase: %s", t);
         }
     });

这篇关于使用Android/Firebase实时数据库时,Single.Create()... blockingGet()在RxJava 2.1.3中挂起的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆