如何通过rxjava2包装侦听器并处理线程切换?

时间:2018-08-28 04:21:38

标签: android firebase firebase-authentication rx-java2

我用下面的代码包装监听器,

public Observable<String> getIdToken() {
    return Observable.create(emitter -> {
        firebaseAuth.getAccessToken(false)
                .addOnSuccessListener(getTokenResult -> {
                    emitter.onNext(getTokenResult.getToken());
                })
                .addOnFailureListener(e -> {
                    if (e instanceof FirebaseAuthInvalidUserException) {
                        emitter.onError(new BaseException("", ERR_CODE_ACCOUNT_BANNED));
                    } else {
                        emitter.onError(e);
                    }
                });
    });
}

public Observable<BaseResponse> register() {
    return getIdToken()
            .flatMap(idToken -> userApi.register(idToken));
}

但遇到错误,

.flatMap(idToken -> userApi.register(idToken));

此代码提示在主线程中运行

firebaseAuth.getAccessToken(false)

内部代码在工作线程中自动切换并执行对Google Firebase的网络请求,当onSuccess成功时,其内部代码切换到nowThread(MainTread),然后执行

            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())

不起作用,但是如何处理该线程切换以在工作线程中创建flatMap?我调用寄存器func如下:

Disposable disposable = UserModel.getInstance().register()
            .subscribeOn(Schedulers.io())
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(baseResponse -> {
                Toast.makeText(this, "a", Toast.LENGTH_SHORT).show();
            }, throwable -> {
                throwable.printStackTrace();
                Log.d("MainActivity111", throwable.getMessage());
            });

logcat提示错误:

08-28 11:18:26.634 6870-6870/? W/System.err: android.os.NetworkOnMainThreadException
    at android.os.StrictMode$AndroidBlockGuardPolicy.onNetwork(StrictMode.java:1450)
    at java.net.AbstractPlainSocketImpl.doConnect(AbstractPlainSocketImpl.java:355)
    at java.net.AbstractPlainSocketImpl.connectToAddress(AbstractPlainSocketImpl.java:200)
    at java.net.AbstractPlainSocketImpl.connect(AbstractPlainSocketImpl.java:182)
    at java.net.SocksSocketImpl.connect(SocksSocketImpl.java:357)
    at java.net.Socket.connect(Socket.java:616)
    at okhttp3.internal.platform.AndroidPlatform.connectSocket(AndroidPlatform.java:71)
    at okhttp3.internal.connection.RealConnection.connectSocket(RealConnection.java:240)
    at okhttp3.internal.connection.RealConnection.connect(RealConnection.java:160)
    at okhttp3.internal.connection.StreamAllocation.findConnection(StreamAllocation.java:257)
    at okhttp3.internal.connection.StreamAllocation.findHealthyConnection(StreamAllocation.java:135)
    at okhttp3.internal.connection.StreamAllocation.newStream(StreamAllocation.java:114)
    at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.java:42)
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
    at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.java:93)
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)

08-28 11:18:26.635 6870-6870/? W/System.err:     at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
    at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.java:93)
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
08-28 11:18:26.636 6870-6870/? W/System.err:     at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.java:126)
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:147)
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:121)
    at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:200)
    at okhttp3.RealCall.execute(RealCall.java:77)
08-28 11:18:26.637 6870-6870/? W/System.err:     at retrofit2.OkHttpCall.execute(OkHttpCall.java:180)
    at retrofit2.adapter.rxjava2.CallExecuteObservable.subscribeActual(CallExecuteObservable.java:42)
    at io.reactivex.Observable.subscribe(Observable.java:12036)
08-28 11:18:26.638 6870-6870/? W/System.err:     at retrofit2.adapter.rxjava2.BodyObservable.subscribeActual(BodyObservable.java:34)
    at io.reactivex.Observable.subscribe(Observable.java:12036)
    at io.reactivex.internal.operators.observable.ObservableFlatMap$MergeObserver.subscribeInner(ObservableFlatMap.java:165)
    at io.reactivex.internal.operators.observable.ObservableFlatMap$MergeObserver.onNext(ObservableFlatMap.java:139)
    at io.reactivex.internal.operators.observable.ObservableCreate$CreateEmitter.onNext(ObservableCreate.java:67)
08-28 11:18:26.639 6870-6870/? W/System.err:     at cn.candrwow.coincoin.model.UserModel.lambda$null$0(UserModel.java:37)
    at cn.candrwow.coincoin.model.-$$Lambda$UserModel$TP1OIyNide1WpDi-afDDpxaJhcE.onSuccess(Unknown Source:4)
    at com.google.android.gms.tasks.zzn.run(Unknown Source:27)
    at android.os.Handler.handleCallback(Handler.java:790)
08-28 11:18:26.640 6870-6870/? W/System.err:     at android.os.Handler.dispatchMessage(Handler.java:99)
    at android.os.Looper.loop(Looper.java:164)
    at android.app.ActivityThread.main(ActivityThread.java:6494)
    at java.lang.reflect.Method.invoke(Native Method)
    at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)

更新

我发现firebase监听器内部代码强制将线程切换到mainThread,而不是调用它的线程,所以出现了以上问题

emitter.onNext(getTokenResult.getToken());

强制进入mainThread,而不是

.subscribeOn(Schedulers.io())

firebase内部代码未打开,我在下面的代码(位于Activity.onCreate中)下登录,发现它强制切换:

new Thread(() -> {
        Log.d("TestActivity", Thread.currentThread().getName());
        FirebaseAuth.getInstance().getAccessToken(false)
                .addOnSuccessListener(getTokenResult -> {
                    Log.d("TestActivity", Thread.currentThread().getName());
                });
    }).start();

logcat是这样的:

    08-28 16:47:47.232 12289-12384/? D/TestActivity: Thread-5
main

我添加.observeOn(Schedulers.io())成功,而Answers的建议也成功。

public Observable<BaseResponse> register() {
    return getIdToken()
//                .observeOn(Schedulers.io())
                .flatMap(idToken -> userApi.register(idToken).subscribeOn(Schedulers.io()));
    }

这是我的UserApi界面:

 public interface UserApi {
    @FormUrlEncoded
    @POST("account/register")
    Observable<BaseResponse> register(@Field("idToken") String idToken);

    @GET("account/testGoogle")
    Observable<BaseResponse> test(@Query("idToken") String idToken);
    }

1 个答案:

答案 0 :(得分:1)

 .flatMap(idToken -> userApi.register(idToken))

可能是

 .flatMap(idToken -> userApi.register(idToken).subscribeOn(Schedulers.io())) 

然后它将起作用。