LiveData 原理与 LiveData 总线

1、概述

LiveData 是一种具有生命周期感知能力的可观察数据持有类,可以保证屏幕上的显示内容和数据一直保持同步。

特点:

  1. LiveData 是一个观察者。它可以感知宿主(Activity 或 Fragment)的生命周期。如果宿主不处于活动状态(屏幕上不可见),LiveData 不会触发没必要的界面更新,这样能避免空指针异常和不必要的性能损耗
  2. LiveData 也是一个被观察者。 如果宿主已经被销毁,LiveData 会自动清空与之连接的 Observer,从而避免内存泄漏

2、使用

2.1 基础使用

引入依赖:

	def lifecycle_version = "2.4.0"

    // Lifecycle only (without ViewModel or LiveData)
    implementation "androidx.lifecycle:lifecycle-runtime:$lifecycle_version"

    // LiveData
    implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version"

    // ViewModel
    implementation "androidx.lifecycle:lifecycle-viewmodel:$lifecycle_version"

LiveData 一般会搭配 ViewModel 一起使用,被封装在 ViewModel 之中,以保证 app 配置变更时,数据不会丢失。首先定义 ViewModel,需持有一个 LiveData:

public class NameViewModel extends ViewModel {

	// LiveData 内封装了 String 类型的数据
    private MutableLiveData<String> name;

    public MutableLiveData<String> getName() {
        if (name == null) {
            name = new MutableLiveData<>();
        }
        return name;
    }
}

然后在 Activity 中生成 ViewModel 对象,并建立 ViewModel 内的 LiveData 的观察者与 Activity 之间的绑定关系:

public class NameActivity extends AppCompatActivity {

    private NameViewModel nameViewModel;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_name);
        final TextView textView = findViewById(R.id.text);

        // 1.获取 NameViewModel 对象
        nameViewModel = new ViewModelProvider(this).get(NameViewModel.class);

        // 2.创建 LiveData 内数据的观察者
        Observer<String> observer = new Observer<String>() {
            @Override
            public void onChanged(String string) {
            	// 当 LiveData 数据发生变化时,将变化后的字符串显示在 textView 上
                textView.setText(string);
            }
        };

        // 3.给观察者与 LifecycleOwner 建立绑定关系
        nameViewModel.getName().observe(this, observer);
    }
}

最后修改 LiveData 的内容,textView 显示的就是 LiveData 被修改后的内容了:

	nameViewModel.getName().setValue("Count:" + (new Random().nextInt(100)));

setValue() 只能在主线程中使用,如果需要在子线程中修改数据,则需要使用 postValue()。

2.2 LiveData 总线

实际开发中通常将所有 LiveData 放在一个 LiveData 数据总线 —— LiveDataBus 上:

public class LiveDataBus {

    private Map<String, MutableLiveData<Object>> bus;
    private static LiveDataBus liveDataBus;

    private LiveDataBus() {
        bus = new HashMap<>();
    }

    public static LiveDataBus getInstance() {
        if (liveDataBus == null) {
            synchronized (LiveDataBus.class) {
                if (liveDataBus == null) {
                    liveDataBus = new LiveDataBus();
                }
            }
        }
        return liveDataBus;
    }

    // 注册观察者,并从 bus 中取出对应的 MutableLiveData
    public synchronized <T> MutableLiveData<T> with(String key, Class<T> type) {
        if (!bus.containsKey(key)) {
            bus.put(key, new MutableLiveData<Object>());
        }
        return (MutableLiveData<T>) bus.get(key);
    }
}

设置数据和观察数据之前都需要先通过 with() 获取到 LiveData:

	// 监听数据
	LiveDataBus.getInstance().with("data", String.class)
                .observe(this, new Observer<String>() {
                    @Override
                    public void onChanged(String string) {
                        Toast.makeText(TestActivity.this,string,Toast.LENGTH_LONG).show();
                    }
                });
-------------------------------------------------------------------
    // 设置数据
    LiveDataBus.getInstance().with("data", String.class).postValue("data changed!");

3、原理

LiveData 的工作流程一般是:

  1. 注册 Observer,将其保存到 LiveData 的 mObservers 集合中
  2. 通过 setValue() 或 postValue() 修改 LiveData 内的数据
  3. LiveData 内的数据被修改,通知 Observer

下面按照流程顺序介绍工作原理。

3.1 注册观察者

LiveData 提供了 observe() 和 observeForever() 两个方法注册观察者:

public abstract class LiveData<T> {

	private SafeIterableMap<Observer<? super T>, ObserverWrapper> mObservers =
            new SafeIterableMap<>();

	@MainThread
    public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
    	// 要求该方法在主线程中使用
        assertMainThread("observe");
        // 如果 owner 已经被销毁就直接返回
        if (owner.getLifecycle().getCurrentState() == DESTROYED) {
            return;
        }
        // 将 observer 包装为 LifecycleBoundObserver 并存入 mObservers
        LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
        // 如果 observer 此前没有被存过,existing 是 null,否则就是之前被存过的包装类对象
        ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
        // 不允许 observer 注册在不同的 owner 上
        if (existing != null && !existing.isAttachedTo(owner)) {
            throw new IllegalArgumentException("Cannot add the same observer"
                    + " with different lifecycles");
        }
        if (existing != null) {
            return;
        }
        // 将包装类对象通过 LifecycleRegistry 注册到 owner 上
        owner.getLifecycle().addObserver(wrapper);
    }
    
	@MainThread
    public void observeForever(@NonNull Observer<? super T> observer) {
        // 要求该方法在主线程中使用
        assertMainThread("observeForever");
        // 将 observer 封装进 AlwaysActiveObserver 并存入 mObservers
        AlwaysActiveObserver wrapper = new AlwaysActiveObserver(observer);
        ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
        // 已经通过 observe() 与 LifecycleOwner 绑定过的 observer 不能再用 observeForever() 注册
        if (existing != null && existing instanceof LiveData.LifecycleBoundObserver) {
            throw new IllegalArgumentException("Cannot add the same observer"
                    + " with different lifecycles");
        }
        if (existing != null) {
            return;
        }
        // 给 ObserverWrapper 的 mActive 赋值为 true 并分发一次数值
        wrapper.activeStateChanged(true);
    }
}

注册观察者时需要注意的信息:

  1. observe() 和 observeForever() 都必须在主线程中调用
  2. observe() 将 Observer 封装成 LifecycleBoundObserver 并注册到 LifecycleOwner,可以感知宿主的生命周期;observeForever() 将 Observer 封装成 AlwaysActiveObserver,没有与 LifecycleOwner 绑定,并设置一直处于活动状态
  3. 同一个 Observer 对象不能注册在不同的 LifecycleOwner 上,并且已经被 observe() 注册过的 Observer 不能再通过 observeForever() 注册

3.2 数据设置

LiveData 提供了两个方法设置其数据,其中 setValue() 只能在主线程中使用,而 postValue() 可以在子线程中使用,但实际上也是切换到主线程然后调用 setValue():

	protected void postValue(T value) {
        boolean postTask;
        synchronized (mDataLock) {
            postTask = mPendingData == NOT_SET;
            mPendingData = value;
        }
        // mPendingData 可以被赋值多次,但是只有第一次赋值时会发送 mPostValueRunnable 任务
        if (!postTask) {
            return;
        }
        // 切换到主线程,实际上执行的是 DefaultTaskExecutor 的 postToMainThread()
        ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
    }

	private final Runnable mPostValueRunnable = new Runnable() {
        @Override
        public void run() {
            Object newValue;
            synchronized (mDataLock) {
            	// 取出 mPendingData 中的值交给 setValue()
                newValue = mPendingData;
                mPendingData = NOT_SET;
            }
            setValue((T) newValue);
        }
    };

ArchTaskExecutor.getInstance() 得到的是一个 DefaultTaskExecutor,而 DefaultTaskExecutor.postToMainThread() 会将任务 post() 到主线程的 Handler 中:

	@Override
    public void postToMainThread(Runnable runnable) {
        if (mMainHandler == null) {
            synchronized (mLock) {
                if (mMainHandler == null) {
                    mMainHandler = new Handler(Looper.getMainLooper());
                }
            }
        }
        mMainHandler.post(runnable);
    }

所以综合看下来,LiveData 的 postValue() 就是在主线程中执行 setValue(),因此我们来看下 setValue() 的内容:

	// LiveData 的版本号,初始值取 START_VERSION 的 -1
	private int mVersion = START_VERSION;
	
	@MainThread
    protected void setValue(T value) {
    	// setValue() 必须只能在主线程
        assertMainThread("setValue");
        // 版本号加 1
        mVersion++;
        mData = value;
        // 传 null 表示通知 LiveData 的所有观察者
        dispatchingValue(null);
    }

这里给 dispatchingValue() 传的是 null 而不是某个具体的 Observer,表示给当前 LiveData 内的 mObservers 中所有的观察者发通知,而不是仅通知某一个观察者:

    void dispatchingValue(@Nullable ObserverWrapper initiator) {
    	// 如果已经在分发数据,又调用 dispatchingValue() 说明又有新的数据需要分发,那么将
    	// mDispatchInvalidated 置为 true 就直接跳过本次分发,这样会导致本次数据丢失
        if (mDispatchingValue) {
            mDispatchInvalidated = true;
            return;
        }
        mDispatchingValue = true;
        do {
            mDispatchInvalidated = false;
            // 调用 activeStateChanged() 时会走这,只通知单个观察者
            if (initiator != null) {
                considerNotify(initiator);
                initiator = null;
            } else {
            	// setValue() 会走这,通知 mObservers 内的所有观察者
                for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =
                        mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
                    considerNotify(iterator.next().getValue());
                    if (mDispatchInvalidated) {
                        break;
                    }
                }
            }
        } while (mDispatchInvalidated);
        mDispatchingValue = false;
    }

通知观察者的具体操作是由 considerNotify() 完成的,在下一节详解该方法。

3.3 通知观察者

considerNotify() 通知观察者是有条件的:

  1. 观察者处于活动状态
  2. 观察者的版本号小于 LiveData 的版本号

具体代码如下:

	private void considerNotify(ObserverWrapper observer) {
		// 观察者不在活动状态,直接返回
        if (!observer.mActive) {
            return;
        }
        
        // 通过 shouldBeActive() 检查到观察者不在活动状态,返回
        if (!observer.shouldBeActive()) {
            observer.activeStateChanged(false);
            return;
        }
        
        // 观察者数据版本号不低于 LiveData 版本号,返回
        if (observer.mLastVersion >= mVersion) {
            return;
        }
        // 满足更新条件,更新版本号并回调观察者的 onChanged()
        observer.mLastVersion = mVersion;
        observer.mObserver.onChanged((T) mData);
    }

参数的 ObserverWrapper 是一个抽象类,它封装了原始的 Observer 并记录了它的状态和版本号:

	private abstract class ObserverWrapper {
        final Observer<? super T> mObserver;
        // 观察者是否处于活动状态,实际上就是宿主是否处于活动状态
        boolean mActive;
        // 最新版本,默认值取 START_VERSION 的 -1
        int mLastVersion = START_VERSION;

        ObserverWrapper(Observer<? super T> observer) {
            mObserver = observer;
        }

		// 是否为活动状态,由子类决定
        abstract boolean shouldBeActive();

        ...
    }

在【3.1 注册观察者】中我们说过,observe() 和 observeForever() 将 observer 封装进了不同的包装类,分别是 LifecycleBoundObserver 和 AlwaysActiveObserver,二者都是 ObserverWrapper 的子类,但是对于活动状态的处理方式有所不同,需要分开来看。

LifecycleBoundObserver

LifecycleBoundObserver 是与生命周期绑定的观察者,在 ObserverWrapper 基础之上,将 LifecycleOwner 封装进来,以获取生命周期状态:

	/**
	* GenericLifecycleObserver 是 LifecycleEventObserver 的子接口,空的,
	* 会在 lifecycle 3.0 上被移除
	*/
	class LifecycleBoundObserver extends ObserverWrapper implements GenericLifecycleObserver {
        @NonNull
        final LifecycleOwner mOwner;

        LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<? super T> observer) {
            super(observer);
            mOwner = owner;
        }

        @Override
        boolean shouldBeActive() {
        	// 至少是 STARTED 状态才认为是处于活动状态,实际上就是 STARTED 和 RESUMED
            return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
        }

        @Override
        public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
        	// 如果 LifecycleOwner,如 Activity/Fragment 已经被销毁,则移除观察者
            if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
                removeObserver(mObserver);
                return;
            }
            // 直接调父类的 activeStateChanged(),传入宿主的状态(是否为活动状态)
            activeStateChanged(shouldBeActive());
        }
        ...
    }

通过以上代码能看出:

  • LifecycleOwner 的生命周期处于 STARTED 和 RESUMED 时是活动状态
  • 如果 LifecycleOwner 已经被销毁,会从 mObservers 中移除该观察者

当 LifecycleOwner 的生命周期发生变化时,会经历如下步骤调用到 onStateChanged():

  1. LifecycleBoundObserver 在向 LifecycleRegistry 注册时,会被包装成 LifecycleEventObserver 封装在 ObserverWithState 中
  2. 当 LifecycleOwner 的生命周期发生变化时,会调用 LifecycleRegistry.ObserverWithState 的 dispatchEvent(),通过 LifecycleEventObserver.onStateChanged() 将生命周期事件通知给 LifecycleBoundObserver

如果对上述过程不熟悉,可以参考 生命周期感知组件 Lifecycle 中的【3.2 生命周期变化的感知与通知】一节。

在 onStateChanged() 内会通过 activeStateChanged() 将 LifecycleOwner 的生命周期状态传入:

	// 子类没有重写 activeStateChanged()
	private abstract class ObserverWrapper {
	    // 活动状态发生改变时被调用,newActive 为 true 表示为活动状态
        void activeStateChanged(boolean newActive) {
            if (newActive == mActive) {
                return;
            }
            // 保存 LifecycleOwner 的状态
            mActive = newActive;
            // 更新 mActiveCount 状态前是否为非活动状态
            boolean wasInactive = LiveData.this.mActiveCount == 0;
            // 更新 mActiveCount
            LiveData.this.mActiveCount += mActive ? 1 : -1;
            // 从非活动状态到活动状态,回调 onActive()
            if (wasInactive && mActive) {
                onActive();
            }
            // 非活动状态回调 onInactive()
            if (LiveData.this.mActiveCount == 0 && !mActive) {
                onInactive();
            }
            // 只有处于活动状态时才会给 LiveData 分发新值
            if (mActive) {
                dispatchingValue(this);
            }
        }
    }

只有 LifecycleOwner 处于活动状态时才会调用 dispatchingValue() 通知当前的观察者,并且在 considerNotify() 内再次检查活动状态以及版本号,满足条件后才会回调 ObserverWrapper 内封装的 Observer 的 onChanged()。像这样在生命周期状态变化时通知观察者,可以保证:

  • 从非活动状态转到活动状态时,观察者能立即获取到最新的 LiveData 数据
  • 从活动状态转到非活动状态时,不通知观察者数据的更新

当然,如果是通过 setValue() 触发 dispatchingValue() 对 mObservers 内所有观察者执行 considerNotify(),也是只有处于活动状态的观察者能接收到 onChanged() 回调。

AlwaysActiveObserver

假如我们使用了 observeForever() 注册观察者,那么会被封装成 AlwaysActiveObserver 存入 LiveData 的 mObservers 集合。AlwaysActiveObserver 顾名思义,是永远处于活动状态的观察者,它重写的 shouldBeActive() 会固定返回 true:

private class AlwaysActiveObserver extends ObserverWrapper {

    AlwaysActiveObserver(Observer<? super T> observer) {
        super(observer);
    }

    @Override
    boolean shouldBeActive() {
        return true;
    }
}

此外,在 observeForever() 内调用 ObserverWrapper.activeStateChanged(true) 将 mActive 置为 true,这样当通过 setValue() 修改 LiveData 数据的时候,调用 dispatchingValue(null) 就会对 mObservers 中的所有观察者执行 considerNotify(),由于 AlwaysActiveObserver 的 mActive 和 shouldBeActive() 一直为 true,因此只要满足 mLastVersion 小于 LiveData 的 mVersion 这个条件,就可以回调 onChanged()。

需要注意的是,由于 AlwaysActiveObserver 没有向 LifecycleOwner 注册,因此只能通过手动调用 removeObserver() 来移除 AlwaysActiveObserver。

4、使用中遇到的问题

4.1 数据丢失问题

数据丢失的情况可能会有多种,一种情况是在老数据还没有分发完成的情况下,又产生了新的需要分发的数据,这时我们要回看一下 LiveData 的 dispatchingValue():

	void dispatchingValue(@Nullable ObserverWrapper initiator) {
    	// 如果已经在分发数据,又调用 dispatchingValue() 说明又有新的数据需要分发,那么将
    	// mDispatchInvalidated 置为 true 就直接跳过本次分发,这样会导致本次数据丢失
        if (mDispatchingValue) {
            mDispatchInvalidated = true;
            return;
        }
        mDispatchingValue = true;
        do {
            mDispatchInvalidated = false;
            if (initiator != null) {
            	// 调用 activeStateChanged() 时会走这,只处理单个观察者
                considerNotify(initiator);
                initiator = null;
            } else {
            	// setValue() 会走这,处理所有观察者
                for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =
                        mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
                    // 遍历 mObservers 取出所有观察者进行通知
                    considerNotify(iterator.next().getValue());
                    if (mDispatchInvalidated) {
                        break;
                    }
                }
            }
        } while (mDispatchInvalidated);
        mDispatchingValue = false;
	}

第一次调用该方法,进入 do-while 循环前会将 mDispatchingValue 赋值为 true 表示正在分发数值,由于通过 setValue() 调用该方法时参数 initiator 传的是 null,所以会走 do-while 内的 else 分支通知所有观察者。

倘若就是在 for 循环之中再次 setValue() 进入 dispatchingValue(),那么 mDispatchInvalidated 会被设置为 true 然后直接返回。此时第一次调用的 dispatchingValue() 在 for 循环内由于 mDispatchInvalidated 为 true 跳出循环,这样就意味着有一部分观察者是没有收到第一次调用 dispatchingValue() 所分发的数值的。

结束 do 循环后,while 条件满足,会再次进入 do 循环,此时再进入 else 分支,通过 for 循环给所有观察者赋新值。

数据丢失还有另一种情况,调用 postValue() 设置数据时,设置数据的速度大于观察者的消费速度:

	protected void postValue(T value) {
        boolean postTask;
        synchronized (mDataLock) {
            postTask = mPendingData == NOT_SET;
            mPendingData = value;
        }
        if (!postTask) {
            return;
        }
        ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
    }

	private final Runnable mPostValueRunnable = new Runnable() {
        @SuppressWarnings("unchecked")
        @Override
        public void run() {
            Object newValue;
            synchronized (mDataLock) {
                newValue = mPendingData;
                mPendingData = NOT_SET;
            }
            setValue((T) newValue);
        }
    };

mPostValueRunnable 只有在被执行时才会去 mPendingData 中取值并传给 setValue() 进行设置,如果在该任务被执行前多次调用 postValue(),实际上只有任务被执行前的最后一次的 mPendingData 被真正的设置了,前面那些都被覆盖了,观察者也没有拿到。

当然了,观察者如果不处于活动状态,设置数据也是不会同步给观察者的。

4.2 粘性问题

粘性问题简单说就是 LiveData 上新注册的观察者接收到了在其注册之前 LiveData 被设置的值。举个例子:

public class StickyTestActivity extends AppCompatActivity {

    private StickyViewModel stickyViewModel;
    private Observer<String> observer;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_sticky_test);

        observer = new Observer<String>() {
            @Override
            public void onChanged(String string) {
                Toast.makeText(StickyTestActivity.this, string, Toast.LENGTH_SHORT).show();
            }
        };

        stickyViewModel = new ViewModelProvider(this).get(StickyViewModel.class);
    }

    private void test() {
        for (int i = 0; i < 10; i++) {
            stickyViewModel.getData().setValue(String.valueOf(i));
            if (i == 6) {
                // 在 setValue(6) 之后注册的观察者,常理来讲不应该收到
                // i = 6 这条消息,但是实际上会收到 
                stickyViewModel.getData().observe(this, observer);
            }
        }
    }

    public void buttonClick(View view) {
        test();
    }
}
----------------------------------------------------
public class StickyViewModel extends ViewModel {

    private MutableLiveData<String> data;

    public MutableLiveData<String> getData() {
        if (data == null) {
            data = new MutableLiveData<>();
        }
        return data;
    }
}

在 test() 的 for 循环中不断向 LiveData 中发数据,当 i = 6 时注册 observer,按照常理来讲,注册动作发生在发送了 i = 6 这条数据之后,所以 observer 不应该收到这条数据,但实际情况是它收到了。这个是因为在注册观察者时,LiveData 的 observe() 会调用到 LifecycleRegistry 的 addObserver(),会调用 sync() 同步一次状态,从而进入状态分发流程,最终调用到 considerNotify():

	private void considerNotify(ObserverWrapper observer) {
        if (!observer.mActive) {
            return;
        }
        
        if (!observer.shouldBeActive()) {
            observer.activeStateChanged(false);
            return;
        }
        // 粘性的原因之一,观察者刚注册的时候版本是 -1,而 LiveData 因为刚刚在
        // 执行 setValue() 时将其初始版本号 + 1 变为 0,这样观察者的版本号小于 
        // LiveData 的版本号,这里不会 return 就会调用 onChanged() 更新数据了
        if (observer.mLastVersion >= mVersion) {
            return;
        }
        observer.mLastVersion = mVersion;
        observer.mObserver.onChanged((T) mData);
    }

能在刚注册就收到之前的数据,观察者的版本号小于 LiveData 的版本号也是原因之一,它是解决粘性问题的切入点。我们可以通过反射修改观察者的版本号,使其等于 LiveData 的版本号,从而满足 considerNotify() 中的第三个 if 条件,使其直接返回不回调 onChanged()。参考代码如下:

public class StickyViewModel extends ViewModel {

    private MutableLiveData<String> data;

    public MutableLiveData<String> getData() {
        if (data == null) {
            data = new DisStickyMutableLiveData<>();
        }
        return data;
    }

    public static class DisStickyMutableLiveData<T> extends MutableLiveData<T> {

        @Override
        public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
            super.observe(owner, observer);
            dismissSticky(this, observer);
        }

        private void dismissSticky(MutableLiveData<?> data, Observer<? super T> observer) {
            try {
                // 反射获取 LiveData 的版本号 mVersion
                Class<?> liveDataClass = LiveData.class;
                Method getVersionMethod = liveDataClass.getDeclaredMethod("getVersion");
                if (!getVersionMethod.isAccessible()) {
                    getVersionMethod.setAccessible(true);
                }
                int liveDataVersion = (int) getVersionMethod.invoke(data);

                // 去 LiveData 的 mObservers 中获取 observer 对应的 ObserverWrapper
                Field mObserversField = liveDataClass.getDeclaredField("mObservers");
                if (!mObserversField.isAccessible()) {
                    mObserversField.setAccessible(true);
                }
                Object mObservers = mObserversField.get(data);
                // SafeIterableMap
                Class<?> mObserversClass = mObservers.getClass();
                Method getMethod = mObserversClass.getDeclaredMethod("get", Object.class);
                if (!getMethod.isAccessible()) {
                    getMethod.setAccessible(true);
                }
                Map.Entry observerWrapperEntry = (Map.Entry) getMethod.invoke(mObservers, observer);

                if (observerWrapperEntry != null) {
                    Object observerWrapper = observerWrapperEntry.getValue();
                    // observerWrapper.getClass() 获得的是 ObserverWrapper 的具体子类,如
                    // LifecycleBoundObserver、AlwaysActiveObserver,但是版本号 mLastVersion
                    // 是定义在父类 ObserverWrapper 中的,所以这里还得再 getSuperclass()
                    Class<?> superclass = observerWrapper.getClass().getSuperclass();
                    // 将观察者版本号设置成与 LiveData 的一致
                    Field mLastVersionField = superclass.getDeclaredField("mLastVersion");
                    if (!mLastVersionField.isAccessible()) {
                        mLastVersionField.setAccessible(true);
                    }
                    mLastVersionField.set(observerWrapper, liveDataVersion);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Room与LiveData、ViewModel结合是为了实现数据持久化、数据观察与界面更新的最佳实践。 Room是Google为Android提供的一个持久化数据库解决方案,它简化了数据库操作并提供了编译时检查,同时支持在后台线程中进行数据库访问。LiveData是一种可观察的数据容器,它可以感知生命周期,并在数据变化时自动更新。ViewModel则负责管理界面相关的数据,并且与Activity或Fragment的生命周期无关,避免了数据丢失或重复请求的问题。 将Room与LiveData结合使用,可以将Room中的数据变化以LiveData的形式暴露出来。这样,在数据库发生变化时,LiveData会自动通知相关观察者进行界面更新。LiveData还具有自动清理机制,当观察者的生命周期结束时会自动停止数据的更新,避免了内存泄漏问题。 而结合ViewModel可以更好地管理界面相关的数据。ViewModel可以在配置改变时(如屏幕旋转)保留数据,并且避免了异步任务导致的内存泄漏。通过在ViewModel中缓存LiveData对象,可以在Activity或Fragment恢复时继续观察数据变化,并保持界面更新的一致性。 总结而言,Room与LiveData、ViewModel的结合可以实现一个可靠、高效、响应式的数据处理框架,使得数据的持久化、观察与界面更新变得十分简单。这样的架构设计也有利于代码的维护与扩展,提高了开发效率与用户体验。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值