代码之家  ›  专栏  ›  技术社区  ›  Michael Dodd

未使用subscribe的结果

  •  149
  • Michael Dodd  · 技术社区  · 8 年前

    今天我升级到了Android Studio 3.1,它似乎又增加了一些lint检查。其中一个lint检查是针对一次性RxJava2的 subscribe() 未存储在变量中的调用。例如,从my Room数据库获取所有玩家的列表:

    Single.just(db)
                .subscribeOn(Schedulers.io())
                .subscribe(db -> db.playerDao().getAll());
    

    结果显示一个大的黄色块和此工具提示:

    的结果 subscribe 未使用

    Screenshot of Android Studio. Code is highlighted in Yellow with a tooltip. Tooltip text: The result of subscribe is not used.

    这种一次性接收呼叫的最佳做法是什么?我应该保留 Disposable dispose() 是否完成?或者我应该 @SuppressLint 然后继续?

    这似乎只会影响RxJava2( io.reactivex ),RxJava( rx )没有这种绒毛。

    8 回复  |  直到 7 年前
        1
  •  147
  •   urgentx Galeb Nassri    8 年前

    IDE不知道您的订阅在未处理时会产生什么潜在影响,因此它将其视为潜在的不安全。例如,您的 Single 可能包含网络调用,如果 Activity 在执行期间被放弃。

    管理大量 Disposable s是使用 CompositeDisposable ;只需创建一个新 CompositeDisposable 实例变量,然后将所有可处置项添加到CompositeDisposable(使用RxKotlin,您可以只附加 addTo(compositeDisposable) 所有一次性用品)。最后,完成实例后,调用 compositeDisposable.dispose()

    这将消除lint警告,并确保 Disposables 管理得当。

    在这种情况下,代码如下所示:

    CompositeDisposable compositeDisposable = new CompositeDisposable();
    
    Disposable disposable = Single.just(db)
            .subscribeOn(Schedulers.io())
            .subscribe(db -> db.get(1)));
    
    compositeDisposable.add(disposable); //IDE is satisfied that the Disposable is being managed. 
    disposable.addTo(compositeDisposable); //Alternatively, use this RxKotlin extension function.
    
    
    compositeDisposable.dispose(); //Placed wherever we'd like to dispose our Disposables (i.e. in onDestroy()).
    
        2
  •  26
  •   Aks4125 Kims Sifers    8 年前

    在活动被销毁的那一刻,一次性物品的清单就被清理干净了,一切都很好。

    io.reactivex.disposables.CompositeDisposable mDisposable;
    
        mDisposable = new CompositeDisposable();
    
        mDisposable.add(
                Single.just(db)
                        .subscribeOn(Schedulers.io())
                        .subscribe(db -> db.get(1)));
    
        mDisposable.dispose(); // dispose wherever is required
    
        3
  •  14
  •   papandreus    6 年前

    您可以订阅 DisposableSingleObserver :

    Single.just(db)
        .subscribeOn(Schedulers.io())
        .subscribe(new DisposableSingleObserver<Object>() {
                @Override
                public void onSuccess(Object obj) {
                    // work with the resulting todos...
                    dispose();
                }
    
                @Override
                public void onError(Throwable e) {
                    // handle the error case...
                    dispose();
                }});
    

    如果您需要直接处理 Single 对象(例如,在其发出之前),您可以实现方法 onSubscribe(Disposable d) 获取并使用 Disposable 参考

    你也可以意识到 SingleObserver 接口或使用其他子类。

        4
  •  5
  •   Vadim Kotov First Zero    7 年前

    正如建议的那样,您可以使用一些全局 CompositeDisposable 在此处添加订阅操作的结果。

    这个 RxJava2Extensions 库包含用于自动从 复合可分解 当它完成时。看见 subscribeAutoDispose 部分

    你的情况可能是这样的

    SingleConsumers.subscribeAutoDispose(
        Single.just(db)
                .subscribeOn(Schedulers.io()),
        composite,
        db -> db.playerDao().getAll())
    
        5
  •  2
  •   blaffie    6 年前

    你可以使用优步 AutoDispose 和rxjava .as

            Single.just(db)
                .subscribeOn(Schedulers.io())
                .as(AutoDispose.autoDisposable(AndroidLifecycleScopeProvider.from(this)))
                .subscribe(db -> db.playerDao().getAll());
    

    请确保您了解何时基于ScopeProvider取消订阅。

        6
  •  1
  •   Dabbler    6 年前

    我一次又一次地回到如何正确处理订阅的问题,尤其是这篇文章。一些博客和谈话声称 dispose 必然会导致内存泄漏,我认为这是一个过于笼统的说法。据我所知,关于不存储 subscribe 在某些情况下不是问题,因为:

    • 并非所有可观察对象都在Android活动的上下文中运行
    • 可观测数据可以是同步的
    • Dispose被隐式调用,前提是observable完成

    由于我不想抑制lint警告,我最近开始对具有同步可观测的情况使用以下模式:

    var disposable: Disposable? = null
    
    disposable = Observable
       .just(/* Whatever */)
       .anyOperator()
       .anyOtherOperator()
       .subscribe(
          { /* onSuccess */ },
          { /* onError */ },
          {
             // onComplete
             // Make lint happy. It's already disposed because the stream completed.
             disposable?.dispose()
          }
       )
    

    我对这方面的任何评论都感兴趣,无论这是对正确性的确认还是发现漏洞。

        7
  •  0
  •   Fernando Prieto Moyano    6 年前

    还有另一种可用的方法,即避免手动使用一次性资源(添加和删除订阅)。

    您可以定义 可观察到 可观察的将从 受试者行为 (如果您使用RxJava)。通过向你的 Live数据 ,这应该行得通。根据初始问题查看下一个示例:

    private val playerSubject: Subject<Player> = BehaviorSubject.create()
    
    private fun getPlayer(idPlayer: String) {
            playerSubject.onNext(idPlayer)
    }
    
    private val playerSuccessful: Observable<DataResult<Player>> = playerSubject
                            .flatMap { playerId ->
                                playerRepository.getPlayer(playerId).toObservable()
                            }
                            .share()
    
    val playerFound: LiveData<Player>
        get() = playerSuccessful
            .filterAndMapDataSuccess()
            .toLiveData()
    
    val playerNotFound: LiveData<Unit>
        get() = playerSuccessful.filterAndMapDataFailure()
            .map { Unit }
            .toLiveData()
    
    // These are a couple of helpful extensions
    
    fun <T> Observable<DataResult<T>>.filterAndMapDataSuccess(): Observable<T> =
    filter { it is DataResult.Success }.map { (it as DataResult.Success).data }
    
    fun <T> Observable<DataResult<T>>.filterAndMapDataFailure(): Observable<DataResult.Failure<T>> =
    filter { it is DataResult.Failure }.map { it as DataResult.Failure<T> }
    
        8
  •  -13
  •   Ivan    8 年前

    如果您确定一次性处理正确,例如使用doOnSubscribe()运算符,则可以将其添加到Gradle:

    android {
    lintOptions {
         disable 'CheckResult'
    }}