LiveData基本教程

版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/feather_wch/article/details/88648559

转载请注明链接: https://blog.csdn.net/feather_wch/article/details/88648559

LiveData基本教程

版本号:2019-04-12(11:30)


简介

1、LiveData的简介

  1. LiveData是一种类,持有可被观察的数据
  2. LiveData是一种可感知生命周期的组件,意味着该组件重视其他app组件的生命周期,如Activity、Fragment、Service
    • 该组件能确保,仅仅在Activity\Fragment\Service等组件都处于活跃的生命周期状态的时候,才去更新app组件。

2、LiveData只有当观察者的生命周期处于活跃状态时才会去通知观察者。

  1. 实现了Observer类的观察者,可以注册监听LiveData
  2. 活跃状态就是指处于STARTED或者RESUMED状态
  3. 处于非活跃的观察者,LiveData不会去通知这些观察者

3、可以注册一种观察者, 该观察者与LifecycleOwner对象(如:Activity、Fragment)相关联。

  1. 在对应的Lifecycle Object处于DESTORYED状态时,会自动解除LiveData和该观察者的注册关系

4、在Activity、Fragment中这种自动解除注册的特性非常有用

  1. Activity、Fragment不用担心会出现内存泄露
  2. Activity、Fragment销毁时,LiveData会自动解除其注册关系

优势

5、LiveData能确保UI和数据状态相符

  1. 因为是观察者模式,LiveData会在生命周期状态改变时,通知观察者
  2. 可以在观察者对象中进行UI的更新操作

6、LiveData没有内存泄露

  1. 观察者和Lifecycle对象绑定,能在销毁时自动解除注册

7、LiveData不会给已经停止的Activity发送事件

  1. 如果观察者处于非活跃状态,LiveData不会再发送任何事件给这些Observer对象

8、LiveData能确保不再需要手工对生命周期进行处理

  1. UI组件仅仅需要对相关数据进行观察
  2. LiveData自动处理生命周期状态改变后,需要处理的代码。

9、LiveData能保证数据最新

  1. 一个非活跃的组件进入到活跃状态后,会立即获取到最新的数据
  2. 不用担心数据问题

10、LiveData在横竖屏切换等Configuration改变时,也能保证获取到最新数据

  1. 例如Acitivty、Fragment因为屏幕选装导致重建, 能立即接收到最新的数据

11、LiveData能资源共享

  1. 如果将LiveData对象扩充,用单例模式系统服务进行包裹。这些服务就可以在app中共享。
  2. 只需要LiveData和系统服务connect,其他观察者只需要监视LiveData就能获取到这些资源

使用LiveData

1、LiveData的使用遵循下面三个步骤

  1. 创建LiveData的实例,并持有具有类型的数据
  2. 创建Observer对象,该对象具有onChanged()方法,在LiveData的数据改变时,会调用onChanged()方法,进行相应的处理工作。可以将Observer放置到activity、fragment
  3. 利用observe()方法ObserverLiveData联系起来。
    * observe()接收一个LifecycleOwner对象
    * 可以使用observeForeve(Observer)注册一个没使用LifecycleOwnerObserver,这种场景中,该Observer会认为是一直存活的。
    * 使用removeObserver(Observer)可以移除这些观察者

创建LiveData对象

2、创建LiveData对象

  1. LiveData能用来包裹所有数据,包括实现了Collections的对象,例如List
  2. LiveData通常存储在ViewModel之中, 并通过get方法来获取
public class UserViewModel extends ViewModel {
    private MutableLiveData<String> mName;
    private MutableLiveData<Integer> mAge;

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

    public MutableLiveData<Integer> getAge() {
        if(mAge == null){
            mAge = new MutableLiveData<>();
        }
        return mAge;
    }
}

3、为什么将LiveData放置到ViewModel中,而不放到activity或者fragment中?

  1. 避免fragment和activity的代码臃肿
  2. LiveData和特定的activity/fragment解耦,能够在configuration改变的时候,LiveData依然存活。

观察LiveData对象

4、在App组件的哪个生命周期适合观察LiveData对象?为什么?

  1. app组件的onCreate()方法
  2. 不适合在onResume()等方法中,可能会调用多次
  3. 能确保组件能尽可能快的展示出数据。只要app组件处于启动状态(STARTED)就会立即接收到LiveData对象中的数据—前提是已经监听了LiveData

5、监听LiveData实例

public class DataBindingActivity extends AppCompatActivity {

    ActivityDatabindingLayoutBinding mBinding;
    User mUser;
    private UserViewModel mUserViewModel;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // DataBinding
        // xxx

        //  1. 创建用户信息的ViewModel
        mUserViewModel = ViewModelProviders.of(this).get(UserViewModel.class);
        //  2. 创建更新UI的观察者
        Observer<String> nameObserver = new Observer<String>() {
            @Override
            public void onChanged(@Nullable String s) {
                // 利用DataBinding更新: 用户账号
                mUser.setAccount(s);
                mBinding.setUser(mUser);
            }
        };
        //  3. 注册观察者
        mUserViewModel.getAccount().observe(this, nameObserver);
    }
}

6、ViewModelProviders为什么找不到?

  1. 引用的版本太老了,需要新的Lifecyle扩展库(目前可以用的最新版)
    android.arch.lifecycle
    // ViewModel and LiveData
    implementation "android.arch.lifecycle:extensions:1.1.1"

androidx

    // 引入lifecycle
    def lifecycle_version = "2.0.0"

    // ViewModel and LiveData
    implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle_version"

更新LiveData对象

7、MutableLiveData类自动提供setValue(T)、postValue(T)用于更新值

8、更新LiveData对象实例

button.setOnClickListener(new OnClickListener() {
    @Override
    public void onClick(View v) {
        String anotherName = "John Doe";
        model.getCurrentName().setValue(anotherName);
    }
});
  1. 调用setValue()或者postValue()都会调用所有观察者的onChanged()方法

Room使用LiveData

9、Room数据持久化库,支持observable查询

  1. 该查询能返回LiveData对象
  2. Observable查询是DAO-Database Access Object的一部分
  3. Room自动生成所有更新LiveData对象所需要的代码(当数据库更新的时候)
  4. 查询操作是在后台线程执行异步操作

扩展的LiveData

1、扩展LiveData

package com.hao.architecture;

import android.arch.lifecycle.LiveData;

import java.math.BigDecimal;

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

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

    private SimplePriceListener listener = new SimplePriceListener() {
        @Override
        public void onPriceChanged(BigDecimal price) {
            // 更新LiveData并且通知所有活跃的观察者
            setValue(price);
        }
    };

    @Override
    protected void onActive() {
        // 具有活跃的观察者时调用
        stockManager.requestPriceUpdates(listener);
    }

    @Override
    protected void onInactive() {
        // 没有任何活跃的观察者时调用
        stockManager.removeUpdates(listener);
    }
}

Fragment中使用

public class MyFragment extends Fragment {
    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        LiveData<BigDecimal> myPriceListener = ...;
        myPriceListener.observe(this, price -> {
            // Update the UI.
        });
    }
}

2、LiveData作为生命周期感知组件,可以在多个Activity中共享: 使用单例

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

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

    //xxx

}

多个Fragment中使用:LiveData仅仅当一个或者多个LifecycleOwner处于活跃状态时,才会和系统服务连接。

public class MyFragment extends Fragment {
    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        StockLiveData.get(symbol).observe(this, price -> {
            // Update the UI.
        });
    }
}

转换LiveData

1、有的时候需要在分发LiveData的数值到观察者前进行处理,可以利用Transformation.map()

LiveData<User> userLiveData = ...;
LiveData<String> userName = Transformations.map(userLiveData, user -> {
    user.name + " " + user.lastName
});

创造新的transformations

2、可以使用MediatorLiveData

合并多个LiveData

1、MediatorLiveData是LiveData的子类

允许merge多个LiveData源

2、LiveData merge的使用场景

  1. 如果具有一个LiveData对象,可以根据本地数据库或者网络数据进行更新
  2. 就可以将两种LiveData来源添加到MediatorLiveData对象中
    1. 和本地数据库关联的LiveData
    2. 和网络数据关联的LiveData
  3. Activity只需要观察MediatorLiveData对象,就能接收到来自两个数据源的更新

LiveData与Lifecycle

1、为什么LiveData能作为生命感知组件

mUserViewModel.getUserListLiveData().observe(ArchActivity.this, new Observer<List<User>>()
        {
            @Override
            public void onChanged(@Nullable List<User> users)
            {
                for (User user : users)
                {
                    Log.d("mvvm", "name = " + user.getName() + " age = " + user.getAge());
                }
            }
        });
  1. LiveData的observe()会将Observer观察者包装成LifecycleObserver
  2. Activity、Fragment这些LifecycleOwner对这些观察者进行注册
  3. 当Activity、Fragment的生命周期改变时,去通知LiveData,作相应处理

2、为什么LiveData只会在观察者的生命周期处于活跃状态时,才去通知观察者更新UI

  1. LiveData对Activity、Fragment的生命周期进行了感知
  2. 当LifecycleOwner的生命周期改变时,会通知LiveData

SingleLiveEvent: 避免observe每次都收到老数据

1、LiveData每次observe进行监听时,都会立即接收到上一次的老数据,但是在某些场景下如MVVM中,只需要收到最新数据。

public class SingleLiveEvent<T> extends MutableLiveData<T>
{
    private static final String TAG = SingleLiveEvent.class.getName();

    private final AtomicBoolean mPending = new AtomicBoolean(false);

    @Override
    @MainThread
    public void observe(@NonNull LifecycleOwner owner, @NonNull final Observer<T> observer)
    {
        if(hasActiveObservers()){
            Log.w(TAG, "Multiple observers registered but only one will be notified of changes.");
        }
        super.observe(owner, new Observer<T>()
        {
            @Override
            public void onChanged(@Nullable T t)
            {
                if(mPending.compareAndSet(true, false)){
                    observer.onChanged(t);
                }
            }
        });
    }

    @Override
    @MainThread
    public void setValue(T value)
    {
        mPending.set(true);
        super.setValue(value);
    }
}

参考资料

  1. LiveData
展开阅读全文

没有更多推荐了,返回首页