これらのピットのためのLiveDataイベント・デリバリーへのAndroidの開発者

LiveDataは、イベントの配信として使用すべき理由1、

(もちろん、多くの欠点があります)、など、良いEventBusおよびプロセスをより明確なアーキテクチャを作り、デカップリングで良いの役割を果たすことができるRxBusの使用であることは言うまでもない作成するために、イベントバスオブザーバーモードを利用して、それぞれの周りに渡されることはありません種コールバック。しかし、彼らはライフサイクルのビュー層(活動、フラグメントなど)の認識が不足している、する必要が手動で手動ライフサイクルが発生しやすい非常に退屈でエラーで管理し、ライフサイクルの終わりにビューアを持ち上げます。

そして、Googleのライブラリのライフサイクルは、観察者LiveDataは、ライフサイクルの認識であり、この問題を、解決することであり、それはライフサイクルイベントバスではなく、宮を作成するために知覚できるならば!

2、イベント配信ピットのために使用されるものとしてLiveData

LiveData使用の段階的な深化で、理解、特にその「ライフサイクル知覚」より深い理解を持って、そしてゆっくりと使用して、いくつかのピットを発見し、共有するには、この機会を利用探索するだけのよう。そして、私は通常、純粋に使用するイベントの配信とLiveDataに持っている、特に、アクションのリスト(など、IOの操作を含む、このような追加や削除などは、ビュー層はデータに変化するかを知る必要があり、操作が成功し、イベントだけの形で送達することができます)。

2.1、postValueデータ損失

また、言及した私の以前の記事では、ソースを直接見ることができます。postValue、実際に設定した値、およびコールバックオブザーバーを保存するためのsetValueを呼び出して、このRunnableを内のRunnableをスローするように、メインスレッドmPendingData、事前に存在していますだけでデータ。postValue Runnableを前に、この何回実行した場合、実際には、ちょうどmPendingDataステージングの値を変更し、再度別のRunnableをスローしません。カバーの前で設定した値の値は、それがイベントの損失につながる後に、この問題が発生します。

 

protected void postValue(T value) {
    boolean postTask;
    synchronized (mDataLock) {
        postTask = mPendingData == NOT_SET;
        // 这里先把数据暂存起来,后来的数据会覆盖前面的
        mPendingData = value;
    }
    // 这里保证只抛一个 mPostValueRunnable,#-.-
    if (!postTask) {
        return;
    }
    ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
}

2.2、setValueのコールバックオブザーバー

意識のLiveDataライフサイクルがここに反映され、それがその後、Viewは意味がありませんアップデートが、より危険なので、それが観測されるまで待機します、コールバック「非アクティブ」の観察者(つまりonPauseにONSTART前後)になりません新しい値の後に、その後、彼へのコールバックをアクティブにします。
しかし、私は、(それはsetValueので覆われていないことが保証されると仮定して)複数のデータを渡す場合、非アクティブ状態にある観察者は知識ではありません、彼らは唯一の活性化の最後の時間にデータを受信します。このイベントの配信は、任意のデータセンターの損失のパフォーマンス上のイベントは、イベント・デリバリーの意味を失っていること、パスを受け取ることができません。

 

// LiveData 通知观察者时调的函数
private void considerNotify(ObserverWrapper observer) {
    // 非激活就直接返回了
    if (!observer.mActive) {
        return;
    }
    // Check latest state b4 dispatch. Maybe it changed state but we didn't get the event yet.
    //
    // we still first check observer.active to keep it as the entrance for events. So even if
    // the observer moved to an active state, if we've not received that event, we better not
    // notify for a more predictable notification order.
    if (!observer.shouldBeActive()) {
        observer.activeStateChanged(false);
        return;
    }
    // 每次更新数据都会版本加一,这里保证不会回调之前发送过的数据
    if (observer.mLastVersion >= mVersion) {
        return;
    }
    observer.mLastVersion = mVersion;
    //noinspection unchecked
    observer.mObserver.onChanged((T) mData);
}

2.3、LiveData イベントを渡すように準備されていません

上記2点からも見ることができるLiveData ビューアを起動する前に(またはそのそれオブザーバー)のデータセンターは、変更を経験した回数を気にしない、それだけで起動時にオブザーバーとなり、彼の最新の値に渡されます、中間の値は動作しません。
もちろん、  LiveData 設計が反応にある場合、通過することはない  View の現在の状態View だけ電流に応じ層  LiveData に不活性の場合、ライン上のデータの値をレンダリングするための  View 更新プログラムがセンスなかった場合でも、表示されていません。
私もほとんど感じるようになった  LiveData オブザーバ・モードで使用し、異なる多くのことができる  Fragment の間でデータ通信を、私はまだあまりにもナイーブ若すぎるだったと思うことを、今、イベントバスと考えます。

もちろん、それは意味しない  LiveData 絶望的ではないが、Googleは強力なを提供してくれますがあります  Lifecycle 私たちはイベントを作る自分自身を失うことができない、ライブラリが  LiveData

図3は、失われたイベントを作成しません。 LiveData

LiveData その他の機能は、我々はそれが上記のような問題のために一つ一つを中断します変換したい、非常に完璧んが、イベントを失うことになります。

3.1、postValue問題

それが最後のコールのsetValueあるだけなのでRunable一度投げているため、データが失われた質問postValueについては、我々は、メインスレッドがこの問題を解決することができRunableを投げるためにあらゆる時間を所有します

 

/**
 * LiveData 相关的工具类,简化 LiveData 操作
 *
 * @author funnywolf
 * @since 2019-04-22
 */
public class LiveDataUtils {
    private static Handler sMainHandler;
    /**
     * 用 setValue 更新 MutableLiveData 的数据,如果在子线程,就切换到主线程
     */
    public static <T> void setValue(MutableLiveData<T> mld, T d) {
        if (mld == null) {
            return;
        }
        if (Thread.currentThread() == Looper.getMainLooper().getThread()) {
            mld.setValue(d);
        } else {
            postSetValue(mld, d);
        }
    }

    /**
     * 向主线程的 handler 抛 SetValueRunnable
     */
    public static <T> void postSetValue(MutableLiveData<T> mld, T d) {
        if (sMainHandler == null) {
            sMainHandler = new Handler(Looper.getMainLooper());
        }
        sMainHandler.post(SetValueRunnable.create(mld, d));
    }

    private static class SetValueRunnable<T> implements Runnable {
        private final MutableLiveData<T> liveData;
        private final T data;

        private SetValueRunnable(@NonNull MutableLiveData<T> liveData, T data) {
            this.liveData = liveData;
            this.data = data;
        }

        @Override
        public void run() {
            liveData.setValue(data);
        }

        public static <T> SetValueRunnable<T> create(@NonNull MutableLiveData<T> liveData, T data) {
            return new SetValueRunnable<>(liveData, data);
        }
    }
}

質問3.2、非アクティブ状態

実際に、私は「責任」の主な問題はLiveDataではありませんが、その視聴者に、「あなたはどのように私は場合には、あなたにそれは、私はあなたを送信されたデータを送信するか、うん、あなたが非アクティブ私に言っていると思います最終的に責任があること、それに伴う問題、?。」
私たちは、公共ボイドは(@NonNull LifecycleOwner所有者、観察呼び出して、視聴者が実際にLifecycleBoundObserverで使用 @NonNullオブザーバー<?スーパーT>オブザーバー)を自動的に私たちのパッケージなどの観察者を助ける、それがLifecycleOwnerのライフサイクルに基づいて表示されます「活性化」と「非アクティブ」状態。

 

// LifecycleBoundObserver
boolean shouldBeActive() {
    return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
}

LiveDataデフォルト別のオブザーバーAlwaysActiveObserverがあり、それはとき、名前が示すように、それは常にアクティブますが、確かではない私たちのためにLiveData生成された私たちの呼び出します。public void observeForever(@NonNullオブザーバー<?スーパーT>観測者)でありますライフサイクル管理のように観察者は、我々は(@NonNull最終オブザーバー<?スーパーT>オブザーバー)観察者が削除手動ます。public void removeObserverを使用して、またはそれはメモリリークかもしれない時に呼び出す必要があります。

 

// AlwaysActiveObserver
boolean shouldBeActive() {
    return true;
}

このAlwaysActiveObserverは、彼が活動している、私たちの問題を解決することができそうですし、すべてのイベントが彼にコールバックを与えるが、私たち自身のライフサイクルを管理する必要があること。これは、それが歴史的後退ではないでしょうか?最後に、ライフサイクルの認識があり、現在は手動で行う必要がありますか?

3.3、イベントのライフサイクルの認識を作成するには、失われた観測者ではありません

手動で絶対に容認されていないのライフサイクルを管理し、AlwaysActiveObserver問題を解決することができるだけであなたは私たちが問題のobserveForeverとremoveObserverを管理するための新たな観測を構築することを、言いました。以下のようにも、ない単にobserveForeverとremoveObserver、非アクティブ状態を独自の観察者に、ライフサイクル管理、それが構築したいと考えているので、それは素敵な最初のイベントは何の意味が失われていないか、あるいはされてはならないになるだろう考慮に入れます。
それはライフサイクルを管理したい場合、それはLifecycleOwner、ライフサイクル、およびライフサイクルLifecycleOwner自分の観測を使用する必要があります。

 

/**
 * Marks a class as a LifecycleObserver. It does not have any methods, instead, relies on
 * {@link OnLifecycleEvent} annotated methods.
 * <p>
 * @see Lifecycle Lifecycle - for samples and usage patterns.
 */
@SuppressWarnings("WeakerAccess")
public interface LifecycleObserver {

}

ライフサイクルは外だけで、このインターフェイスに任意の引き戻しが含まれていない、我々は反射によってマークされたライフサイクル機能を取得し、それに対応するアダプタ、興味缶の外観を生成します、レーンはOnLifecycleEventノートを言ったコメントで適切な関数をマークする必要がありますLifecycling.getCallback機能の下で。例えば、我々は使用することができます

 

public class Observer implements LifecycleObserver {
    @OnLifecycleEvent(Lifecycle.Event.ON_START)
    private void onStart() {
        doSomethingOnStart();
    }
}

最初に我々はできる、ライフサイクルをゲット  observeForeverで、  Lifecycle.Event.ON_DESTROY 時間  removeObserver
次は、アクティブと非アクティブ状態とみなされ、以降は費やすことにする  observeForeverと、この時間があれば、すべてのイベントがコールバックを持っていることを、  Lifecycle アクティブになって、それがイベントに直接送出することができます。しかし、非アクティブの場合、イベントが直接出て送信することはできません、我々は失う、そして私たちは、その後、最初のイベントを保存する必要がないことができ  Lifecycle 、イベントが送出されたときに、それがアクティブになり、その後、保存します。シンプルなフローチャートは、ドローダウン。

画像

 

/**
 * LiveData 用作事件传递时的观察者
 * 保证所有事件不丢失,保存非激活状态的事件,并能够在激活状态回调,且没有内存泄漏
 *
 * @see AsEventBus
 *
 * @author funnywolf
 * @since 2019-05-18
 */
public class LiveEventObserver<T> implements LifecycleObserver, Observer<T> {
    private LiveData<T> mLiveData;
    private LifecycleOwner mOwner;
    private Observer<? super T> mObserver;

    private final List<T> mPendingData = new ArrayList<>();

    public LiveEventObserver(LiveData<T> liveData, LifecycleOwner owner, Observer<? super T> observer) {
        mLiveData = liveData;
        mOwner = owner;
        mObserver = observer;
        mOwner.getLifecycle().addObserver(this);
        mLiveData.observeForever(this);
    }

    /**
     * 在生命周期结束前的任何时候都可能会调用
     */
    @Override
    public void onChanged(@Nullable T t) {
        if (isActive()) {
            // 如果是激活状态,就直接更新
            mObserver.onChanged(t);
        } else {
            // 非激活状态先把数据存起来
            mPendingData.add(t);
        }
    }

    /**
     * @return 是否是激活状态,即 onStart 之后到 onPause 之前
     */
    private boolean isActive() {
        return mOwner.getLifecycle().getCurrentState()
                .isAtLeast(Lifecycle.State.STARTED);
    }

    /**
     * onStart 之后就是激活状态了,如果之前存的有数据,就发送出去
     */
    @OnLifecycleEvent(Lifecycle.Event.ON_ANY)
    private void onEvent(LifecycleOwner owner, Lifecycle.Event event) {
        if (owner != mOwner) {
            return;
        }
        if (event == Lifecycle.Event.ON_START || event == Lifecycle.Event.ON_RESUME) {
            for (int i = 0; i < mPendingData.size(); i++) {
                mObserver.onChanged(mPendingData.get(i));
            }
            mPendingData.clear();
        }
    }

    /**
     * onDestroy 时解除各方的观察和绑定,并清空数据
     */
    @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
    private void onDestroy() {
        mLiveData.removeObserver(this);
        mLiveData = null;

        mOwner.getLifecycle().removeObserver(this);
        mOwner = null;

        mPendingData.clear();

        mObserver = null;
    }

    public static <T> void bind(@NonNull LiveData<T> liveData,
                                @NonNull LifecycleOwner owner,
                                @NonNull Observer<? super T> observer) {
        if (owner.getLifecycle().getCurrentState() == Lifecycle.State.DESTROYED) {
            return;
        }
        new LiveEventObserver<>(liveData, owner, observer);
    }
}

3.4 LiveDataイベントの更新を確保

3.1また、公共空間をオーバーライドする必要が(@NonNull LifecycleOwner所有者、@NonNullオブザーバー<?スーパーT>オブザーバー)を観察する当社独自の定義ことを確認するために、オブザーバーが続き、自分のpostValueに対処すると言われています。

 

/**
 * 用作事件总线的 {@link MutableLiveData}
 *
 * @see AsEventBus
 *
 * @author funnywolf
 * @since 2019-05-18
 */
public class EventMutableLiveData<T> extends MutableLiveData<T> {
    @Override
    public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
        LiveEventObserver.bind(this, owner, observer);
    }

    @Override
    public void postValue(T value) {
        LiveDataUtils.setValue(this, value);
    }
}

/**
 * 用作事件总线的 {@link MediatorLiveData}
 *
 * @see AsEventBus
 *
 * @author funnywolf
 * @since 2019-05-18
 */
public class EventMediatorLiveData<T> extends MediatorLiveData<T> {
    @Override
    public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
        LiveEventObserver.bind(this, owner, observer);
    }

    @Override
    public void postValue(T value) {
        LiveDataUtils.setValue(this, value);
    }
}

/**
 * 该注解只用于 {@link androidx.lifecycle.LiveData},用于表示 LiveData 是当成事件总线用的,需要注意:
 * - 观察者在非激活状态(onStart 之后,onPause 之前)时不会产生回调,会丢失事件
 * - postValue 可能会被覆盖,只能用 setValue 来更新值
 * - LiveData 的事件都是黏性的,不使用时手动抛出一个 null 事件,以防下次绑定时会发送存在之前的旧数据;
 *
 * @see LiveDataUtils
 * @see LiveEventObserver
 * @see EventMutableLiveData
 * @see EventMediatorLiveData
 *
 * @author funnywolf
 * @since 2019-05-06
 */
@Target(ElementType.FIELD)
public @interface AsEventBus {
}

4、LiveDataUtils他のツールの紹介

ツールバッグは、私は通常、いくつかの他の一般的に使用されるガジェットがあり、単にここであなたと共有します:

  • StateDataは、ステータスとエラーメッセージをパッケージのデータが含まれていLiveDataのみコールバックをonChangedイベントので、あなたは、データの状態を知ることができない、このクラスに従事します
  • RxLiveDataはMutableLiveDataから継承された、使い捨てオブザーバインタフェースを実現し、主にLiveDataへRxJavaからデータ変換のため
  • LiveDataBus、バスベースのLiveDataイベントが、お勧めできません。それは機会が非常に香りが書かれた作品は、非常にメンテナンス後に面倒ではないんではない場合を除きイベントバスは、このようなものを使用しないようにしてください

注意あなたは、ああ、より高度な情報技術の乾燥やAndroidのシェアを見ることができます

公開された56元の記事 ウォンの賞賛1 ビュー2907

おすすめ

転載: blog.csdn.net/chuhe1989/article/details/104641636