Android架构组件之LiveData

如果你看过了Android架构组件之Lifecycle,可以立马投入到LiveData组件的学习中,同样的,LiveData也是Google I/O 大会上发布的架构组件,ListData是一个可被观察的数据持有类,为我们什么需要使用LiveData?主要有以下几个有点:
更多参考

一,保证数据与界面的实时更新

LiveData采用了观察者模式设计,其中LiveData是被观察者,当数据发生变化时会通知观察者进行数据更新。通过这点,可以确保数据和界面的实时性。

二,有效避免内存泄漏

这是因为LiveData能够感知到组件的生命周期,当组件状态处于DESTROYED状态时,观察者对象会被remove

三,Activity/Fragment销毁掉时不会引起崩溃

这是因为组件处于非激活状态时,在界面不会收到来自LiveData的数据变化通知。这样规避了很多因为页面销毁之后,修改UI导致的crash

四,不需要手动处理生命周期

LiveData能够感知组件的生命周期,所以设置LiveData组件的生命周期状态。

五,始终能够保持最新数据

生命周期从非活跃状态切换到活跃状态的时候,能够实时的接收最新的数据。

六,能够应对配置更改

由于LiveData保存数据的时候,组件和数据是分离的,所以在配置更改(如横竖屏切换等)的时候,即便组件被重新创建,因为数据还保存在LiveData中,这样也能够做到实时的更新。

七,资源共享

单例模式扩展LiveData对象并包装成系统服务,以便在应用程序中进行共享,需要该资源的只需要观察LiveData即可。

LiveData的使用

相关Gradle配置参考

通常使用LiveData有三个步骤:
1,创建LiveData实例来保存数据,常常是配合ViewModel一起工作;
2,定义一个Observer的观察者对象,如果有数据更新会通过观察者的onChanged()方法来同步到UI上面;
3,将观察者Observer通过observe()方法进行绑定。

LiveData有两种使用方法:一种是直接使用,如接下来的例子;还有一种是继承LiveData的实现资源共享的方式。
直接使用的时候,LiveData一般和ViewModel一起使用。
首先定义个MyNameViewModel

class MyNameViewModel : ViewModel() {
    // Create a LiveData with a String
    private var mCurrentName: MutableLiveData? = null
    // Create a LiveData with a String list
    private var mNameListData: MutableLiveData>? = null

    open fun currentName(): MutableLiveData {
        if (mCurrentName == null) {
            mCurrentName = MutableLiveData()
        }
        return mCurrentName as MutableLiveData
    }

    open fun nameList(): MutableLiveData> {
        if (mNameListData == null) {
            mNameListData = MutableLiveData()
        }
        return mNameListData as MutableLiveData>
    }
}
class FirstActivity : AppCompatActivity() {
    companion object {
        val TAG = FirstActivity.javaClass.simpleName
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        val myNameViewModel = ViewModelProviders.of(this).get(MyNameViewModel::class.java)
        myNameViewModel.currentName().observe(this, Observer {
            print(it)
        })

        myNameViewModel.nameList().observe(this, Observer {
            if (it != null) {
                for (item in it) {
                    print(item)
                }
            }
        })
    }

ViewModel里面,定义两个方法,currentName,和nameList两个方法,并返回LiveData对象。然后在activity中通过ViewModelProviders.of(this).get(MyNameViewModel::class.java)拿到viewModel,最后通过observe设置监听,observe方法里面的两个参数LifecycleOwner ownerObserver,最后在onChanged方法中回调数据(这里kotlin代码使用的是lamdba表达式)。

用两个按钮模仿修改ViewModel中保存的LiveData数据:

   btn_change_name.setOnClickListener {
            myNameViewModel.currentName().setValue("Hubery")
   }

    btn_update_list.setOnClickListener {
          var nameList = ArrayList()
            for (i in 0..9) {
                nameList.add("Hubery<$i>")
            }
            myNameViewModel.nameList().setValue(nameList)
    }

现在来看看LiveData资源共享,也就是继承LiveData的例子:

class StockLiveData(symbol: String) : LiveData() {
    private val mStockManager: StockManager

    private val mListener = object : SimplePriceListener() {
        fun onPriceChanged(price: BigDecimal) {
            setValue(price)
        }
    }

    init {
        mStockManager = StockManager(symbol)
    }

    override fun onActive() {
        mStockManager.requestPriceUpdates(mListener)
    }

    override fun onInactive() {
        mStockManager.removeUpdates(mListener)
    }
}

LiveData对象具有活动的观察者时调用OnActive方法。LiveData中的数据会调用setValue方法去更新。
LiveData在没有任何的Observer监听的时候,会调用Inactive方法,在这里的例子会removeUpdate方法。

LiveData的原理

借鉴ShymanZhu同学的关系图

LiveData_one.png

LiveData:是LiveData组件里面非常核心的一个类,主要实现了observe方法用于注册监听,setValue用于主线程设置值,而postValue子线程和主线程都可以。

MutabeLiveData:继承了LiveDataLiveData是一个抽象类不能直接使用,在子类里面重写了postValuesetValue两个方法;

MediatorLiveDataMediatorLiveData继承了MutabeLiveData

LifecycleBoundObserverLifecycleBoundObserverLiveData的内部类,
它继承了ObserverWrapper并实现了GenericLifecycleObserver,而这个GenericLifecycleObserver又实现了LifecycleObserver,有没有很熟悉?在Lifecycle组件中通过LifecycleObserver便可以观察到LifecycleOwner中持有的Lifecycle对象的生命周期变化。

ObserverLiveData有数据更新的时候就是通过Observer接口的onChanged方法告知界面(Activity,Fragment)

再次感谢ShymanZhu同学的时序图

LiveData_two.png

上面大致的思路是:在Fragment中调用observe()方法的时候,会先在方法内创建一个LifecycleBoundObserver对象,然后通过getLifecycle().addObserver()将这个创建好的对象添加进去。当生命周期会发生改变的时候,会调用相应的方法,移除观察者或者通知观察者更新数据;另外的调用LiveDatasetValue()postValue()方法后,也会通知观察者更新数据。

我们首先根据上面的思路理一下,首选需要注册观察者,创建LifecycleBoundObserver对象,生命周期发生变化之后通知观察者修改数据。

添加观察者

添加观察者有两个方法可以调用,observeobserveForever,先来看看这两个方法的实现:

   @MainThread
    public void observe(@NonNull LifecycleOwner owner, @NonNull Observer observer) {
        if (owner.getLifecycle().getCurrentState() == DESTROYED) {
            // ignore
            return;
        }
        LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
        ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
        if (existing != null && !existing.isAttachedTo(owner)) {
            throw new IllegalArgumentException("Cannot add the same observer"
                    + " with different lifecycles");
        }
        if (existing != null) {
            return;
        }
        owner.getLifecycle().addObserver(wrapper);
    }

observe方法中需要将LifecycleOwner传入,而LifecycleOwner的实现类可以通过getLifecycle(),拿到Lifecycle的生命周期;而observeForever则不需要传入:

   @MainThread
    public void observeForever(@NonNull Observer observer) {
        AlwaysActiveObserver wrapper = new AlwaysActiveObserver(observer);
        ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
        if (existing != null && existing instanceof LiveData.LifecycleBoundObserver) {
            throw new IllegalArgumentException("Cannot add the same observer"
                    + " with different lifecycles");
        }
        if (existing != null) {
            return;
        }
        wrapper.activeStateChanged(true);
    }

通过observeForever()添加的观察者,会永久收到数据变化的回调,除非用户手动removeObserve()观察者会一直收到数据的变化的回调通知。

生命周期变化

先看看LifecycleBoundObserver 类的源码实现:

  class LifecycleBoundObserver extends ObserverWrapper implements GenericLifecycleObserver {
        @NonNull final LifecycleOwner mOwner;

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

        @Override
        boolean shouldBeActive() {
            return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
        }

        @Override
        public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
            if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
                removeObserver(mObserver);
                return;
            }
            activeStateChanged(shouldBeActive());
        }

        @Override
        boolean isAttachedTo(LifecycleOwner owner) {
            return mOwner == owner;
        }

        @Override
        void detachObserver() {
            mOwner.getLifecycle().removeObserver(this);
        }
    }
void activeStateChanged(boolean newActive) {
            if (newActive == mActive) {
                return;
            }
            // immediately set active state, so we'd never dispatch anything to inactive
            // owner
            mActive = newActive;
            boolean wasInactive = LiveData.this.mActiveCount == 0;
            LiveData.this.mActiveCount += mActive ? 1 : -1;
            if (wasInactive && mActive) {
                onActive();
            }
            if (LiveData.this.mActiveCount == 0 && !mActive) {
                onInactive();
            }
            if (mActive) {
                dispatchingValue(this);
            }
        }

添加了观察者之后,生命周期发生改变的时候就会调用onStateChanged()方法,当前的状态处于DESTROYED的时候,观察者会被remove,当当前的状态为active的时候,调用activeStateChanged()方法。

LiveData的数据更新

上面我们提到过,LiveData的数据更新有两种方式,第一种就是使用setValue的方式只能在主线程也就是UI线程里面调用,另外一种就是postValue的方式可以在主线程或者子线程里面调用。

public class MutableLiveData extends LiveData {
    @Override
    public void postValue(T value) {
        super.postValue(value);
    }

    @Override
    public void setValue(T value) {
        super.setValue(value);
    }
}

setValuepostValueLiveData中的实现:

@MainThread
    protected void setValue(T value) {
        assertMainThread("setValue");
        mVersion++;
        mData = value;
        dispatchingValue(null);
    }

 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() {
        @Override
        public void run() {
            Object newValue;
            synchronized (mDataLock) {
                newValue = mPendingData;
                mPendingData = NOT_SET;
            }
            //noinspection unchecked
            setValue((T) newValue);
        }
    };

通过源码看到,postValue最后也会调用setValue方法,去修改LiveData中的值。

你可能感兴趣的:(Android架构组件之LiveData)