Android进阶 ——— Android官方架构组件LiveData

本文详细探讨了Android的LiveData,一个感知生命周期的数据容器。LiveData在数据变化时自动通知界面更新,确保在组件处于活跃状态时进行操作。文章介绍了如何创建和使用LiveData,包括直接使用和继承自定义,以及其原理,强调了与ViewModel配合的优势。
摘要由CSDN通过智能技术生成

上一篇文章,学习了Android官方架构组件的第一部分Android进阶 ——— Android官方架构组件Lifecycle

初探

LiveData 是一个可以感知 Activity 、Fragment生命周期的数据容器。当 LiveData 所持有的数据改变时,它会通知相应的界面代码进行更新。同时,LiveData 持有界面代码 Lifecycle 的引用,这意味着它会在界面代码(LifecycleOwner)的生命周期处于 started 或 resumed 时作出相应更新,而在 LifecycleOwner 被销毁时停止更新。

  • 意味着LiveData可以被观察者订阅,并且感知LifeCycleOwner组件的生命周期。
  • 如果LifecycleOwner的状态为Lifecycle.State.STARTEDLifecycle.State.RESUMED,才会通知观察者更新
  • 可以通过observeForever(Observer)添加的观察者,使其始终处于活动状态,不仅仅是处于活跃状态。但是这种方式添加的观察者,需要手动调用removeObserver(Observer)解除

上面的描述介绍了LiveData的优点:不用手动控制生命周期,不用担心内存泄露,数据变化时会收到通知。

不仅如此,官方推荐,LiveData和Viewmodel搭配使用,ViewModel是Android官方构件的另一成员。

ViewModel 将视图的数据和逻辑从具有生命周期特性的实体(如 Activity 和 Fragment)中剥离开来。直到关联的 Activity 或 Fragment 完全销毁时,ViewModel 才会随之消失,也就是说,即使在旋转屏幕导致 Fragment 被重新创建等事件中,视图数据依旧会被保留。ViewModels 不仅消除了常见的生命周期问题,而且可以帮助构建更为模块化、更方便测试的用户界面。

ViewModel的优点:为Activity 、Fragment存储数据,直到完全销毁。尤其是屏幕旋转的场景,常用的方法都是通过onSaveInstanceState()保存数据,再在onCreate()中恢复,真的是很麻烦。
其次因为ViewModel存储了数据,所以ViewModel可以在当前Activity的Fragment中实现数据共享。

使用

LiveData有几种使用方式:
- 使用LiveData对象
- 继承LiveData

1.使用LiveData对象

  使用LiveData对象主要有以下几个步骤:

  • 创建保存特定数据类型的LiveData实例(ViewModel中);
  • 创建Observer对象,作为参数传入LiveData.observe()方法,添加观察者;
  • 通过 observe()方法连接观察者和LiveData。observe()方法需要携带一个LifecycleOwner类。这样就可以让观察者订阅LiveData中的数据;
创建LiveData实例,一般继承自MutableLiveData

MutableLiveData是LiveData的子类,添加了公共方法setValue和postValue,方便开发者直接使用。setValue必须在主线程调用。postValue可以在后台线程中调用。

/**
 * Created by dai
 * Created time 2018/8/20
 * function:lifecycle.example.com.lifecycleexample.LifeCycle
 */

public class MainViewModel  extends ViewModel{


    private MutableLiveData<Student> student =  new MutableLiveData<>();

    public MutableLiveData<Student> getStudent() {
        return student;
    }

    public void addStudent(){
        Student student1 = new Student();
        student1.setGender(55);
        student1.setName("zhangsan");
        student.setValue(student1);
    }

}
创建Observer对象,作为参数添加观察者

通过LiveData.observe()方法添加观察者,当数据变化时会通过回调方法通知观察者

/**
 * Created by dai
 * Created time 2018/8/20
 * function:lifecycle.example.com.lifecycleexample
 */

public class MainActivity extends AppCompatActivity {

    private MainPresenter presenter;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        presenter = new MainPresenter();
        getLifecycle().addObserver(presenter);
        final TextView textView = findViewById(R.id.text);
        Button button = findViewById(R.id.button);
        ViewModelProvider.NewInstanceFactory  factory = new ViewModelProvider.NewInstanceFactory();
        final MainViewModel model = factory.create(MainViewModel.class);
        //订阅数据变化
        model.getStudent().observe(this, new Observer<Student>() {
            @Override
            public void onChanged(@Nullable Student student) {
                textView.setText(student.getName());
                Log.e(student.getName(),student.getGender() + "年级");
            }
        });
}
更新LiveData中的数据

点击button,修改LiveData数据,观察者观察到数据变化,打印出信息

        //修改数据
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                model.addStudent();
            }
        });
    }
2.继承LiveData

在LiveData中,onActive方法回调表明当前Activity处于激活状态,也就是Activity处于生命周期的活动状态中(onStart,onResume),可以简单认为当前的Activity处于前台。LiveData的onInactive处理涉及onActive剩下的生命周期

1)创建继承于MutableLiveData

自定义一个MyThread继承MutableLiveData,内部实现一个简单的功能,后台运行一个长时的线程任务,该线程实现一个简单功能:
(1)如果当前的Activity处于运行(用户可见)状态,则线程任务不断累计计数器并postValue一个值给任何Observer使用。
(2)如果当前Activity处于没有激活状态,则暂停线程任务,停止累计计数器。


/**
 * Created by dai
 * Created time 2018/8/21
 * function:lifecycle.example.com.lifecycleexample
 */

public class MyThread extends MutableLiveData<Integer> {

    private Integer a = 0;
    private boolean Active = true;

    private Thread thread = new Thread(new Runnable() {
        @Override
        public void run() {
            while (Active){
                a++;
                postValue(a);
            }

        }
    });

    public MyThread(){
        thread.start();
    }

    @Override
    protected void onInactive() {
        super.onInactive();
        Log.e("aa","onInactive");
        Active = false;
    }

    @Override
    protected void onActive() {
        super.onActive();
        Log.e("aa","onActive");
        Active = true;
        thread.interrupt();

    }
}
2)构建Observer

再构建Observer,在Observer的onChanged中监听变化
在LiveData中的数据变化,通过postValue(可后台线程)或者setValue(主线程)设置后,将触发Observer的onChanged,开发者只需onChanged等待最新数据回调即可。

public class MainActivity extends AppCompatActivity {

    private MainPresenter presenter;
    private TextView textView;
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        textView  = findViewById(R.id.text);
        MyThread thread = new MyThread();
        thread.observe(this,new MyObserver());

    }


    private class MyObserver implements Observer<Integer> {

        @Override
        public void onChanged(@Nullable Integer number) {
            Log.e("Main",number.intValue()+"");
            textView.setText(number.toString());
        }
    }

}

LiveData原理

先来熟悉一下类图,再分源码

这里参考一下Android架构组件(二)——LiveData

类关系图

LiveData的类关系图相对比较简单,从上面的类图我们就能看到。和LiveData组件相关的类和接口有:LiveData类、Observer接口、GenericLifecycleObserver接口。
LiveData类是个抽象类,但是它没有抽象方法,抽象类有个特点是:不能在抽象类中实例化自己。为什么LiveData会被定义成abstract而又没有抽象方法呢,这个…我也不知道,看了下LiveData的提交记录,是在将hasObservers()替换getObserverCount()方法时将LiveData改成了abstract,在此之前它是被定义为public,可以翻墙的可以看下这里的修改记录

  • MediatorLiveData继承自MutableLiveData,MutableLiveData继承自LiveData。MediatorLiveData可以看成是多个LiveData的代理,当将多个LiveData添加到MediatorLiveData,任何一个LiveData数据发生变化时,MediatorLiveData都会收到通知。

  • LiveData有个内部类LifecycleBoundObserver,它实现了GenericLifecycleObserver,而GenericLifecycleObserver继承了LifecycleObserver接口。在这里可以回顾下Lifecycle组件相关的内容。当组件(Fragment、Activity)生命周期变化时会通过onStateChanged()方法回调过来。

  • Observer接口就是观察者,其中定义了LiveData数据变化的回调方法onChanged()。

时序图
时序图

LiveData主要涉及到的时序有三个:

  • 在Fragment/Activity中通过LiveData.observer()添加观察者(observer()方法中的第二个参数)。
  • 根据Fragment/Activity生命周期发生变化时,移除观察者或者通知观察者更新数据。
  • 当调用LiveData的setValue()、postValue()方法后,通知观察者更新数据。

最让人头疼的源码,这里只抽取出常用方法


    //添加观察者,普通模式,只在LifecycleOwner处于活跃状态,监听LiveData的变化
    @MainThread
    public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<T> observer) {
          if (owner.getLifecycle().getCurrentState() == DESTROYED) {
              // ignore
              return;
          }
          //将LifecycleOwner对象和Observer对象封装成LifecycleBoundObserver对象。
          LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
          // mObservers可以理解成一个类似Map的容器,putIfAbsent()方法是判断容器中的observer(key)
          // 是否有已经和wrapper(value)关联,如果已经关联则返回关联值,否则关联并返回wrapper。
          LifecycleBoundObserver existing = mObservers.putIfAbsent(observer, wrapper);
          if (existing != null && existing.owner != wrapper.owner) {
              throw new IllegalArgumentException("Cannot add the same observer"
                      + " with different lifecycles");
          }
          if (existing != null) {
              return;
          }
          owner.getLifecycle().addObserver(wrapper); 
          //条件LifecycleOwner的生命周期观察者

    }

    /**通过observeForever()添加观察者,观察者会一直受到数
    据的变化回到,而不是在组件处于STARTED和RESUMED状态下才
    会收到,因为这是LifecycleOwner对象就不再是组件了,而是
    ALWAYS_ON;另外通过该方法添加观察者后,要手动调用
    removeObserver()方法来停止观察者接收回调通知。
    observeForever()方法体很简单,调用了observe()方法
    ,传入的一个参数是ALWAYS_ON常量
    */
    @MainThread
    public void observeForever(@NonNull Observer<T> observer) {

    }

      /**移除观察者,如果不是主线程,则会警告,然后根据
      observer取出对应的ObserverWrapper(SafeIterableMap中存储Observer和
      ObserverWrapper),真正实现移除是在
      removed.activeStateChanged(false)中
      */
    @MainThread
    public void removeObserver(@NonNull final Observer<T> observer) {
        assertMainThread("removeObserver");
        //mObservers是一个SafeIterableMap对象
        ObserverWrapper removed = mObservers.remove(observer);
        if (removed == null) {
            return;
        }
        removed.detachObserver();
        //真正移除Observer的监听
        removed.activeStateChanged(false);
    }

      /**
      移除全部观察者,同样必须主线程,然后遍历所有Observer,调用removeObserver移除Observer
      */
    @MainThread
    public void removeObservers(@NonNull final LifecycleOwner owner) {
        assertMainThread("removeObservers");
        for (Map.Entry<Observer<T>, ObserverWrapper> entry : mObservers) {
            if (entry.getValue().isAttachedTo(owner)) {
                removeObserver(entry.getKey());
            }
        }
    }

      //主/分线程都可以调用,如果主线程多次调用,只调度最后一个值
    protected void postValue(T value) {
        boolean postTask;
        synchronized (mDataLock) {
            postTask = mPendingData == NOT_SET;
            mPendingData = value;
        }
        if (!postTask) {
            return;
        }
       // 会在主线程中执行  mPostValueRunnable中的内容。
       ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
    }

      //判断主线程,
    @MainThread
    protected void setValue(T value) {
        assertMainThread("setValue");
        mVersion++;
        mData = value;
        dispatchingValue(null);
    }

      //获取数据,很简单
    public T getValue() {
          Object data = mData;
        if (data != NOT_SET) {
            //noinspection unchecked
            return (T) data;
        }
        return null;
    }

      //活跃状态,空方法,子类实现
    protected void onActive() {

    }
      //非活跃状态,空方法,子类实现
    protected void onInactive() {

    }
      //是否有观察者
    public boolean hasObservers() {
        return mObservers.size() > 0;
    }
      //是否有活跃观察者
    public boolean hasActiveObservers() {
        return mActiveCount > 0;
    }

    private abstract class ObserverWrapper {
        final Observer<T> mObserver;
        boolean mActive;
        int mLastVersion = START_VERSION;

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

        abstract boolean shouldBeActive();

        boolean isAttachedTo(LifecycleOwner owner) {
            return false;
        }

        void detachObserver() {
        }

        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();
            }
            //如果活跃状态观察者为0,且移除观察者,则非活跃状态
            if (LiveData.this.mActiveCount == 0 && !mActive) {
                onInactive();
            }
            if (mActive) {
                dispatchingValue(this);
            }
        }
    }

总结

简单了解LiveData的使用以及原理,发现内部并不太复杂,一直是维护一个观察者和观察者管理对象的 SafeIterableMap,现在就可以在轻松的开始尝试了。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值