Los desarrolladores de Android a la entrega de sucesos LiveData para los boxes

1, ¿por qué debería LiveData utilizado como entrega de eventos

Aprovechar el modo de observador bus de eventos para crear ni que decir (por supuesto, hay muchas deficiencias), como es bien EventBus y el uso RxBus puede jugar un papel bueno en la disociación, que el proceso de arquitectura más clara, y no va a ser pasado alrededor de cada especies de devolución de llamada. Pero carecen de la percepción de la capa de la vista (Actividad, Fragmento, etc.) del ciclo de vida, la necesidad de levantar manualmente el espectador al final de su ciclo de vida, manejar manualmente el ciclo de vida es muy tedioso y propenso a errores.

Y la Biblioteca del ciclo de vida de Google es resolver este problema, que tiene observador LiveData es una percepción del ciclo de vida, si puede ser percibido para crear un bus de eventos del ciclo de vida, no Miya!

2, LiveData como los utilizados para pit entrega de eventos

En la profundización gradual del uso LiveData y entender, especialmente su "percepción ciclo de vida" tener una comprensión más profunda, y poco a poco descubre una cisterna de modo utilizado, al igual que para tomar esta oportunidad para compartir explorar. Y normalmente tienen que LiveData puramente como la entrega de eventos para su uso, en particular, una lista de acciones (tales como adiciones y supresiones que implican la operación de IO, ver las necesidades de capa para saber qué cambios de los datos, y la operación tiene éxito, etc., sólo puede ser entregado en forma de eventos).

2.1, la pérdida de datos postvalue

En mi artículo anterior también se ha mencionado, se puede mirar directamente a la fuente. postvalue sólo los datos que viene pre-existente a mPendingData, a continuación, el hilo principal para lanzar un ejecutable, en este Ejecutable que a su vez llama a la setValue a ahorrar hasta el valor realmente de configurar, y los observadores de devolución de llamada. Si esto muchas veces antes postvalue Ejecutable ejecutados, de hecho, sólo cambia el valor de mPendingData puesta en escena, y no va a lanzar otro nuevo ejecutable. Este problema se produce después de que el valor del valor establecido en el frontal de la cubierta, que dará lugar a la pérdida del evento.

 

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 ningún observador de devolución de llamada

LiveData ciclo de vida de la conciencia se refleja aquí, no estará en la devolución de llamada "inactivo" observador (es decir, antes después onStart a onPause), porque entonces actualizar la vista no tiene sentido, pero más peligrosa, esperará hasta que el observador después de que el nuevo valor a continuación, activar una devolución de llamada para él.
Pero si paso múltiples de datos (suponiendo que se garantiza que no se cubre con setValue), un observador que está en un estado inactivo hay conocimiento, sólo se reciben los datos en el último momento de la activación. Esta entrega de eventos, los eventos en el rendimiento de la pérdida de cualquier centro de datos no puede recibir un pase, que perdió el sentido de la entrega del evento.

 

// 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 no está preparado para pasar el evento

También se puede observar de lo anterior dos puntos, LiveData (o que es observador) antes de activar el espectador no le importa cuántas veces el centro de datos experimentó un cambio, sólo será un observador en el momento de la activación, pasó a su último valor , el valor medio no va a funcionar.
Por supuesto,  LiveData el diseño no es para pasar el evento, que es una reacción a  View la situación actual de la View capa justo de acuerdo a la corriente  LiveData para hacer que el valor de los datos de la línea, cuando está inactivo  View no es visible, incluso si la actualización no hizo sentido.
También empecé a sentir el más  LiveData utilizado en el modo observador, y puede ser un número de diferentes  Fragment comunicación de datos entre, pienso en el bus de eventos, ahora que lo pienso todavía era demasiado joven demasiado ingenuo.

Por supuesto, no quiere decir que  LiveData no es desesperada, hay Google nos proporciona una potente  Lifecycle biblioteca, no podemos perder el hacer de un evento  LiveData.

3, no crea un evento perdido LiveData

LiveData Otras características hacen muy perfecto, pero perderá el evento, que quieren transformar se romperá uno por uno para el problema anterior.

3.1, problemas postvalue

Para preguntas postvalue, ya que es el último setValue llamada, los datos se pierde debido a que sólo una vez lanzado runable, entonces poseemos cada vez que el hilo principal para lanzar un poder capaz de correr para resolver este problema

 

/**
 * 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);
        }
    }
}

Pregunta 3.2, el estado inactivo

De hecho, creo que el principal problema de la "responsabilidad" no está en la LiveData, pero en sus espectadores, "me estás diciendo que INACTIVO Sí, ¿cómo les puedo enviar los datos, te lo envió, en caso de que problemas con él, que al final quien es el responsable ?. "
Se utilizó el espectador es en realidad LifecycleBoundObserver, llamando public void observar (propietario @NonNull LifecycleOwner, @NonNull Observador <? Super T> observador) será automáticamente ayudarnos un paquete de estos observadores, y se mostrará basado en el ciclo de vida de LifecycleOwner la "activación" y el estado "inactivo".

 

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

LiveData defecto no es otra AlwaysActiveObserver observador, que es nuestro llamado observeForever public void (@NonNull Observador <? Super T> observador) se genera cuando, como su nombre indica lo hará siempre activa, LiveData ciertamente no para nosotros como observador de la gestión del ciclo de vida, tenemos que llamar cuando no esté usando el manual removeObserver public void (@NonNull observador final <? super T> observador) observadora removido, o puede ser una pérdida de memoria.

 

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

Este AlwaysActiveObserver parece capaz de resolver nuestros problemas, ha estado activo, y que todos los acontecimientos le dará una devolución de llamada, pero necesidad de gestionar nuestro propio ciclo de vida. Esto no es un retroceso histórico que? Por último, existe la percepción de su ciclo de vida, y ahora tienen que hacerlo de forma manual?

3.3, crear una percepción del ciclo de vida de los acontecimientos no es observador perdida

Gestionar manualmente el ciclo de vida es absolutamente no tolerará, AlwaysActiveObserver problema puede ser resuelto sólo le dijo que construimos un nuevo observador para gestionar el problema y observeForever removeObserver. Ya que quiere construir, que sería un buen primer evento no debe perderse, o de lo contrario no tiene sentido; y gestión del ciclo de vida a su propio observador, no simplemente observeForever y removeObserver, estado inactivo también como tenido en cuenta.
Si se quiere gestionar el ciclo de vida, tendría que utilizar LifecycleOwner, ciclo de vida, y sus propias observaciones LifecycleOwner del ciclo de vida.

 

/**
 * 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 {

}

Ciclo de vida fuera sólo para esta interfaz no contiene ningún retroceso, tenemos que marcar la función apropiada con un comentario Lane dijo notas OnLifecycleEvent, conseguirán funciones del ciclo de vida marcado por la reflexión, y luego generar el correspondiente adaptador, mirada puede interesarle bajo la función Lifecycling.getCallback. Por ejemplo, podemos utilizar

 

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

Obtener el ciclo de vida, lo que podamos desde el principio  observeForever, en  Lifecycle.Event.ON_DESTROY el momento  removeObserver.
Al lado de ser considerados estado activo e inactivo, y puesto que pasó  observeForever, y que cada caso tendrá devolución de llamada, si esta vez  Lifecycle es activo, que puede ser enviado directamente al evento. Pero si está inactivo, el evento no se pueden enviar directamente, no podemos perder, entonces tenemos que ahorrar hasta el primer evento, a continuación,  Lifecycle a continuación, guardar el medicamento se activa cuando el evento enviado. simple diagrama de flujo dispuesto.

imagen

 

/**
 * 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 garantizar la actualización de eventos LiveData

3.1 Se dice también que lidiar con su propio postvalue, seguido por observadores para asegurar que nuestra propia definición, que sobreescribir public void observar (propietario @NonNull LifecycleOwner, @NonNull Observador <? Super T> observador).

 

/**
 * 用作事件总线的 {@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 otras herramientas Introducción

La bolsa de herramientas por lo general hay algunos otro dispositivo comúnmente usado, simplemente compartir con ustedes aquí:

  • StateData contiene mensajes de estado y error de empaquetado de datos, debido a LiveData onChanged solamente una devolución de llamada, no se puede conocer el estado de los datos, se dedican a esta clase
  • RxLiveData heredado de MutableLiveData, y se dio cuenta interfaz desechable Observer, principalmente para la conversión de datos desde el RxJava a LiveData
  • LiveDataBus, un evento LiveData basada en autobús, pero no se recomienda. Bus caso trate de no usar este material, salvo que no sea motivo no funciona, escrita cuando muy aromático, muy molesto después del mantenimiento

La atención se puede ver más avanzada tecnología de la información y seca cuota de Android oh

Publicado 56 artículos originales · ganado elogios 1 · vistas 2907

Supongo que te gusta

Origin blog.csdn.net/chuhe1989/article/details/104641636
Recomendado
Clasificación