LiveData はコールバックを受け取りません

新しいプロジェクトで使用されている LiveData フレームワークですが、ある日、LiveData によって登録されたリッスン コールバックが一度だけ出力され、その後は消えないことに気づきました。そこで、その理由を調べに行ってきました。最終的にトライキャッチが原因であることが分かりました。

サンプルコード:

私のコードはおそらく次のようになります: クラッシュを防ぐためにメソッドでtry catch が使用されています

    val mBanner=MutableLiveData<List<Banner>>()
    fun test(){
        println("1")
        try {
            mBanner.observe(this){
                println("2")
                throw  RuntimeException("奔溃了")
                println("3")
            } 
        }catch (e:Exception){
            
        }
        println("4")
    }

//打印的结果: 1,2,4

デバッグ後、初めてクラッシュする限り、このコールバックは二度と使用されないことがわかりました。したがって、バグは tyr catch に関連しているはずです。

LiveData でイベントを配信する方法を見てみましょう。また、以下でマークされた場所でデバッグすると、 mDispatchingValue が常に true であることが判明し、その結果、次のステップを実行できなくなりました。そして、mDispatchingValue はグローバル変数です。では、この値はどこで false に設定されるのでしょうか? 次のメソッドの マークに示されているように、メソッド全体が実行された後でのみ false に設定されます。

 void dispatchingValue(@Nullable ObserverWrapper initiator) {
        if (mDispatchingValue) {   //在此处debug
            mDispatchInvalidated = true;
            return;
        }
        mDispatchingValue = true;
        do {
            mDispatchInvalidated = false;
            if (initiator != null) {
                considerNotify(initiator);
                initiator = null;
            } else {
                for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =
                        mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
                    considerNotify(iterator.next().getValue()); //分发事件
                    if (mDispatchInvalidated) {
                        break;
                    }
                }
            }
        } while (mDispatchInvalidated);
        mDispatchingValue = false;  //方法执行完毕后置为falses
    }

これで、問題は非常に明確になりました。メソッドの呼び出し時にクラッシュし、catch が直接実行され、後続のコードが実行されず、その結果、dispatchingValue メソッドが最後まで実行されず、mDispatchingValue が常に実行されなかったためです。本当だった。

解決:

では、クラッシュを回避し、同時に修正するにはどうすればよいでしょうか?

登録されたコールバックがクラッシュする箇所でtry catchでラップすることで、 dispatchingValueが確実に実行されるようにします

    val mBanner=MutableLiveData<List<Banner>>()
    fun test(){
        println("1")
        try {
            mBanner.observe(this){
                try {
                    println("2")
                    throw  RuntimeException("奔溃了")
                    println("3")
                }catch (e:Exception){

                }
            }
        }catch (e:Exception){

        }
        println("4")
    }

次のメソッドに示すように、LiveData拡張関数をカプセル化して書き換えて、コールバック メソッドに try catch を与え、コールバック メソッドが完了できることを確認し、 dispatchingValueが完了しないことを回避します。 

fun <T> MutableLiveData<T>.safeObserve(owner: LifecycleOwner, onChange: (T) -> Unit) {
    this.observe(owner) {
        try {
            onChange(it)
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }
}

おすすめ

転載: blog.csdn.net/xueyoubangbang/article/details/129713106