Android Jetpack 架构组件(五) LiveData

LiveData的初衷:防止开发者疏忽而忘记释放监听对象。具体表现是:开发者不用在onDestory()里写unregister()了。仅此!

 

概念要点:

1. LiveData能绑定Activity、Fragment 或 Service的生命周期。之所以能感知是因为Activity、Fragment 或 Service事先已经实现好了Lifecycle的功能。

2. active是指Activity、Fragment 或 Service处于started或者resumed。其他状态就是inactive。

3. LiveData仅更新处于active(活跃状态)的observer,而inactive(非活跃状态)的observer就不会接到更新。

4. 绑定生命周期后,就不需要手动remove observer。

5. LiveData也可以不绑定Activity、Fragment 或 Service的生命周期,而一直处于active状态。但是这就需要开发者手动remove observer。

6. 存在粘性事件问题。只要一监听,旧值就会传过来。无法设置或取消粘性事件。 所以要考虑到自己的业务适配问题。

7. postValue()是异步方法,存在吞值问题。如果旧值还没有分发到UI线程。那就会被新值覆盖。

 

创建 LiveData 对象

LiveData可以封装对象类型的数据,也包括各种List类型。

LiveData 对象通常存储在 ViewModel 对象中,可以避免 Activity 和 Fragment 过于庞大。 功能划分上,Activity 和 Fragment 只负责显示数据,ViewModel负责存储数据状态。

现在Databinding已经算成熟了,用Databinding基本可以替代LiveData在ViewModel中的作用了。当然不排除业务上还有用的到LiveData的场景。

 

在ViewModel 中可通过 getter 方法进行访问,如以下示例中所示:

    public class NameViewModel extends ViewModel {

    // Create a LiveData with a String
    private MutableLiveData<String> currentName;

        public MutableLiveData<String> getCurrentName() {
            if (currentName == null) {
                currentName = new MutableLiveData<String>();
            }
            return currentName;
        }

    // Rest of the ViewModel...
    }
    

更新 LiveData 对象

LiveData是抽象类,也没有公开 setValue(T) 和 postValue(T) 。是通过MutableLiveData 类才公开了 setValue(T) 和 postValue(T) 方法,可以修改存储在 LiveData 对象中的值。

setValue(T) 主线程调用。postValue(T)可以在后台线程调用,最终会回调到主线程。

通常情况下会在 ViewModel 中使用 MutableLiveData,然后 ViewModel 只会向观察者公开不可变的 LiveData 对象。

 

扩展 LiveData

这个主题讲的是如何利用好onActive()/onInactive() 这两个回调方法。这种方式是很有用的,如果是register/unregiser的业务,可以首先想到扩展LiveData的onActive()/onInactive() 来简化UI上的代码。

以下示例代码说明了如何扩展 LiveData 类:

    public class StockLiveData extends LiveData<BigDecimal> {
        private StockManager stockManager;

        private SimplePriceListener listener = new SimplePriceListener() {
            @Override
            public void onPriceChanged(BigDecimal price) {
                setValue(price);
            }
        };

        public StockLiveData(String symbol) {
            stockManager = new StockManager(symbol);
        }

        @Override
        protected void onActive() {
            stockManager.requestPriceUpdates(listener);
        }

        @Override
        protected void onInactive() {
            stockManager.removeUpdates(listener);
        }
    }
    

本例中的价格监听器实现包括以下重要方法:

当 LiveData 对象具有活跃观察者时,会调用 onActive() 方法。这意味着,从此方法开始观察股价更新。

当 LiveData 对象没有任何活跃观察者时,会调用 onInactive() 方法。由于没有观察者在监听,因此没有理由与 StockManager 服务保持连接。

setValue(T) 方法将更新 LiveData 实例的值,并将更改通知给任何活跃观察者。

使用 StockLiveData 类:

    public class MyFragment extends Fragment {
        @Override
        public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
            super.onViewCreated(view, savedInstanceState);
            LiveData<BigDecimal> myPriceListener = ...;
            myPriceListener.observe(getViewLifeycleOwner(), price -> {
                // Update the UI.
            });
        }
    }
    

observe() 方法将与 Fragment关联的 LifecycleOwner 作为第一个参数传递。这样做表示此观察者已绑定到与所有者关联的 Lifecycle 对象,这意味着:

  • 如果 Lifecycle 对象未处于活跃状态,那么即使值发生更改,也不会调用观察者。
  • 销毁 Lifecycle 对象后,会自动移除观察者。

LiveData 对象具有生命周期感知能力,这一事实意味着您可以在多个 Activity、Fragment 和 Service 之间共享这些对象。为使示例保持简单,可以将 LiveData 类实现为单例

    public class StockLiveData extends LiveData<BigDecimal> {
        private static StockLiveData sInstance;
        private StockManager stockManager;

        private SimplePriceListener listener = new SimplePriceListener() {
            @Override
            public void onPriceChanged(BigDecimal price) {
                setValue(price);
            }
        };

        @MainThread
        public static StockLiveData get(String symbol) {
            if (sInstance == null) {
                sInstance = new StockLiveData(symbol);
            }
            return sInstance;
        }

        private StockLiveData(String symbol) {
            stockManager = new StockManager(symbol);
        }

        @Override
        protected void onActive() {
            stockManager.requestPriceUpdates(listener);
        }

        @Override
        protected void onInactive() {
            stockManager.removeUpdates(listener);
        }
    }
    

在 Fragment 中使用它:

    public class MyFragment extends Fragment {
        @Override
        public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
            super.onViewCreated(view, savedInstanceState);
            StockLiveData.get(symbol).observe(getViewLifecycleOwner(), price -> {
                // Update the UI.
            });
        }
    }
    

以上是来自官方的例子。

再举一个网络连接的例子:

public class NetworkLiveData extends LiveData<NetworkInfo> {
    private Context mContext;
    private static NetworkLiveData mNetworkLiveData;
    private NetworkReceiver mNetworkReceiver;
    private final IntentFilter mIntentFilter;

    private NetworkLiveData() {
        mNetworkReceiver = new NetworkReceiver();
        mIntentFilter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);
    }

    @MainThread
    public static NetworkLiveData get() {
        if (mNetworkLiveData == null) {
            mNetworkLiveData = new NetworkLiveData();
        }

        return mNetworkLiveData;
    }

    public NetworkLiveData with(Context context) {
        mContext = context.getApplicationContext();
        return mNetworkLiveData;
    }

    @Override
    protected void onActive() {
        super.onActive();
        mContext.registerReceiver(mNetworkReceiver, mIntentFilter);
    }

    @Override
    protected void onInactive() {
        super.onInactive();
        mContext.unregisterReceiver(mNetworkReceiver);
    }

    private static class NetworkReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            ConnectivityManager manager = (ConnectivityManager) context
                    .getSystemService(Context.CONNECTIVITY_SERVICE);
            NetworkInfo activeNetwork = manager.getActiveNetworkInfo();
            get().with(context).setValue(activeNetwork);
        }
    }
}

 

最后是源码解析:

LiveData类代码,即使包括了大量的注释也就492行代码。因为系统的Activity/fragment已经实现好了lifecycle的功能。所以代码也就大大简化了。

上面的UML图阐述了基本结构。

LiveData类

这个抽象类有下面几个重要方法:

public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer)

向LiveData添加观察者。其中LifecycleOwner 就是activity和fragment,因为它们实现了Lifecycle。


public void observeForever(@NonNull Observer<? super T> observer) 

与observe不同,observeForever没有生命周期,它永远都是活跃状态,所以只要有数据更新就一定能接收到。因为没有生命周期控制,所以需要开发者手动removeObserver(observer)。


protected void setValue(T value)
protected void postValue(T value)

这两个方法分别实现数据更新。更新后观察者observer如果是活跃状态就能接到数据。setValue要在主线程调用,postValue可以在其他线程下调用。

这两个方法是protected的,需要继承后才能使用。MutableLiveData类就是干了这事,也只干了这事。


protected void onActive()  //Called when the number of active observers change to 1 from 0. 有第一活跃观察者的时候调用。
protected void onInactive() //Called when the number of active observers change from 1 to 0. 一个活跃观察者都没有的时候。

这两个方法是和生命周期联系在一起的,也是扩展LiveData的时候使用的。前面有讲到它们的作用。

但是和observeForever是没有关系的。因为observeForever永远是活跃状态。


public void removeObserver(@NonNull final Observer<? super T> observer)
public void removeObservers(@NonNull final LifecycleOwner owner) 

上面两个方法就是移除观察者。在MediatorLiveData中也有用到。请看后面一篇文章

之所以开发者不需要手动调removeObserver,是因为LifecycleBoundObserver类在接到DESTORYED状态后,调用了removeObserver。

在removeObserver中,

removed.detachObserver();//mOwner.getLifecycle().removeObserver(this);移除Lifecycle的监听
removed.activeStateChanged(false);//设置非活跃状态。看看是否是最后一个活跃的,如果是就调用onInactive。

除了方法外,还有一个重要的参数:

private volatile Object mData = NOT_SET;

LiveData封装的值。观察者观察的目标对象。

private int mVersion = START_VERSION;

也就是mData的version。mVersion 决定了是不是要通知活跃观察者更新数据。会和Observer接收到的data version比较,也就是mLastVersion。初始是START_VERSION == -1

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

存储了所有的观察者,包括活跃的和非活跃的。

ObserverWrapper类

这个抽象类是对Observer的封装。 

封装了什么呢?

1. mLastVersion, 用于和LiveData的mVersion比较。

2. mActive,记录是否活跃状态。

3. 可以桥接Lifecycle, 获得LifecycleOwner的实时状态,用activeStateChanged接收Lifecycle状态,决定是否调用active/inactive,以及分发更新的数据。

4.用 abstract boolean shouldBeActive();定义活跃状态。在此也可以定义永远是活跃状态,只要返回true就可以了。

LifecycleBoundObserver类

这个类中正式桥接了Lifecycle。

1. 实现了GenericLifecycleObserver。LifecycleOwner会返回Lifecycle状态。

2. 定义了活跃状态。mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);

3. 用onStateChanged接受Lifecycle状态。如果是DESTORYED就移除监听。用activeStateChanged去分发状态。

AlwaysActiveObserver类

这个类是没有生命周期的。它始终是活跃状态。是个observerForever()相对应的。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值