LiveData的使用和源码解析

什么是LiveData

官方定义如下:

LiveData是一个可以观察的数据存储类,不同于常规的可观察类,LiveData具有生命周期感知能力,意味着它遵从app组件(比如Activity、Fragment或Service)的生命周期,这种感知能力可确保 LiveData仅更新处于活跃生命周期状态的app组件的观察者。

拆解开来主要有3个方面:

  1. LiveData是一个数据持有者,给源数据包装一层。
  2. LiveData具有生命周期感知能力。
  3. LiveData更新数据只发生在组件(Activity/Fragment/Service)活跃生命周期状态(STARTED、RESUMED)。

使用LiveData的优势:

  1. 确保UI符合数据的状态,LiveData遵循观察者模式,当对应的数据发生变化时,LiveData会通知Observer对象。你可以在这些Observer对象中更新UI,就不需要每次数据发生改变时更新UI了。
  2. 没有内存泄露,当关联的组件为DESTROYED状态时,Observer对象自己会回收掉。
  3. 不会有Activity停止导致的崩溃,如果关联组件的生命周期状态是inactive,比如一个activity进入后台后,它不会再收到任何LiveData事件。
  4. 数据始终是最新的,如果当前生命周期为inactive,它将在再次变为active状态时接收到最新的数据。比如,一个在后台的Activity在回到前台后马上会接收最新的数据。
  5. 不再需要手动处理生命周期,UI组件只需要观察对应的数据,LiveData会自动进行管理,因为LiveData可以感知对应组件生命周期的变化。
  6. 合理的配置更改,如果一个Activity或Fragment由于配置更改导致重建,比如屏幕旋转,重建后马上会收到最新的数据。
  7. 共享资源,你可以用LiveData结合单例来封装系统服务,这样就可以在应用中共享这个系统服务了。

基本使用

看如下代码:

java 复制代码
public class MyActivity extends AppCompatActivity {

   private static final String TAG = MyActivity.class.getSimpleName();

   private MutableLiveData<String> mLiveData;
   
   @Override
   protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       
       mLiveData = new MutableLiveData<>();
       mLiveData.observe(this, new Observer<String>() {
           @Override
           public void onChanged(String s) {
               Log.i(TAG, "onChanged: "+s);
           }
       });
       Log.i(TAG, "onCreate: ");
       mLiveData.setValue("onCreate");
   }
   
   @Override
   protected void onStart() {
       super.onStart();
       Log.i(TAG, "onStart: ");
       mLiveData.setValue("onStart");
   }
   
   @Override
   protected void onResume() {
       super.onResume();
       Log.i(TAG, "onResume: ");
       mLiveData.setValue("onResume");
   }
   
   @Override
   protected void onPause() {
       super.onPause();
       Log.i(TAG, "onPause: ");
       mLiveData.setValue("onPause");
   }
   
   @Override
   protected void onStop() {
       super.onStop();
       Log.i(TAG, "onStop: ");
       mLiveData.setValue("onStop");
   }
   
   @Override
   protected void onDestroy() {
       super.onDestroy();
       Log.i(TAG, "onDestroy: ");
       mLiveData.setValue("onDestroy");
   }
}

这里先使用MutableLiveData对String进行了包装,然后使用LiveData的observe()方法把new Observer<String>()添加为观察者,最后使用setValue()更新数据,onChanged()方法就会回调。

进入MyActivity打印如下:

less 复制代码
MyActivity    com.example.test  I  onCreate: 
MyActivity    com.example.test  I  onStart: 
MyActivity    com.example.test  I  onChanged: onStart
MyActivity    com.example.test  I  onResume: 
MyActivity    com.example.test  I  onChanged: onResume

按Home键键打印如下:

less 复制代码
MyActivity    com.example.test  I  onPause: 
MyActivity    com.example.test  I  onChanged: onPause
MyActivity    com.example.test  I  onStop: 

再次进入MyActivity打印如下:

less 复制代码
MyActivity    com.example.test  I  onStart: 
MyActivity    com.example.test  I  onChanged: onStart
MyActivity    com.example.test  I  onResume: 
MyActivity    com.example.test  I  onChanged: onResume

退出MyActivity打印如下:

less 复制代码
MyActivity    com.example.test  I  onPause: 
MyActivity    com.example.test  I  onChanged: onPause
MyActivity    com.example.test  I  onStop: 
MyActivity    com.example.test  I  onDestroy: 

通过上面的打印看到,只有onStart()、onResume()、onPause()之后才有onChanged()方法回调。 这就是LiveData的特性,只更新关联组件活跃生命周期状态(STARTED或RESUMED)的数据。

在上一篇Lifecycle的使用和源码解析有如下代码:

java 复制代码
//在API 29及以上 
static class LifecycleCallbacks implements Application.ActivityLifecycleCallbacks {
    
    @Override 
    public void onActivityPostStarted(@NonNull Activity activity) {
       dispatch(activity, Lifecycle.Event.ON_START); 
    } 
    
    @Override 
    public void onActivityPostResumed(@NonNull Activity activity) {
       dispatch(activity, Lifecycle.Event.ON_RESUME); 
    } 
    
    @Override 
    public void onActivityPrePaused(@NonNull Activity activity) {
       dispatch(activity, Lifecycle.Event.ON_PAUSE); 
    }    
    
    @Override 
    public void onActivityPreStopped(@NonNull Activity activity) {
       dispatch(activity, Lifecycle.Event.ON_STOP); 
    }
    
}  

可以看到在API 29及以上Lifecycle.Event.ON_START和Lifecycle.Event.ON_RESUME分别在onStart()和onResume()之后分发,Lifecycle.Event.ON_PAUSE和Lifecycle.Event.ON_STOP分别在onPause()和onStop()之前分发。

又根据上图,执行onStart()之后分发ON_START,此时所处的状态为STARTED;执行onResume()之后分发ON_RESUME,此时所处的状态为RESUMED;执行onPause()之前分发ON_PAUSE,此时所处的状态为STARTED。在STARTED和RESUMED状态时都会回调onChanged()方法。而onStop()执行之前会分发ON_STOP,此时状态变成CREATED,此时就不会再onChanged()方法了。

另外,还可以使用observeForever(Observer) 方法来添加不需要关联LifecycleOwner的观察者。在这种情况下,观察者会被视为始终处于活跃状态。

继承LiveData

如果observer处于STARTED或RESUMED状态,LiveData会认为observer处于活跃状态。以下示例代码说明了如何继承LiveData类:

java 复制代码
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);
    }
}

上例中的重要方法有:

  1. onActive()方法,当LiveData实例有一个活跃观察者的时候调用,你需要在这里关注股价的变化。
  2. onInactive()方法,当LiveData实例没有活跃观察者的时候调用,你需要在这里断开与StockManager的联系。
  3. setValue()方法,这个方法是用来更新LiveData的值的,它会通知所有的活跃观察者。 你可以这样用StockLiveData:
java 复制代码
public class MyFragment extends Fragment {
    @Override
    public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) {
        super.onViewCreated(view, savedInstanceState);
        LiveData<BigDecimal> myPriceListener = ...;
        myPriceListener.observe(getViewLifecycleOwner(), price -> {
            // Update the UI.
        });
    }
}

这里observe()方法会把fragment的LifecycleOwner作为第一个参数传入,这样做表示此观察者与LifecycleOwner进行了绑定。observe()方法会添加观察者,组件进入DESTROYED状态会自动移除观察者。

你也可以把上例改成一个单例,这样多个Activity、Fragment或Service就可以共享LiveData实例:

java 复制代码
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);
    }
}

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.
        });
    }
}

Transform LiveData

如果你想要在分发给observer之前修改LiveData中的数据,或者你可能需要返回一个不同的LiveData实例,你可以使用LiveData提供的Transformations类。

  1. Transformations.map(),可以对LiveData中的数据进行修改并向下游传递。
java 复制代码
public class MyActivity extends AppCompatActivity {

    private static final String TAG = MyActivity.class.getSimpleName();

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        MutableLiveData<User> userLiveData = new MutableLiveData<>();
        
        LiveData<String> userName = Transformations.map(userLiveData, new Function<User, String>() {
                @Override
                public String apply(User user) {
                    return user.name + " " + user.lastName;
                }
        });
        
        userName.observe(this, new Observer<String>() {
            @Override
            public void onChanged(String s) {
                Log.d(TAG, "the name is:" + s);
            }
        });

        userLiveData.setValue(new User("Jim", "Green"));
    }

    static class User{
        private String name;
        private String lastName;
        public User(String name, String lastName){
            this.name = name;
            this.lastName = lastName;
        }
    }
}

打印如下:

csharp 复制代码
MyActivity    com.example.test    D  the name is:Jim Green
  1. Transformations.switchMap(),可以修改LiveData中的数据,返回一个新的不同的LiveData实例。如下是一个根据地址返回邮编的实例:
java 复制代码
public class MyActivity extends AppCompatActivity {
    private static final String TAG = MyActivity.class.getSimpleName();
    private MutableLiveData postCodeLiveData =  new MutableLiveData<Integer>();

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        MutableLiveData<String> addressInput = new MutableLiveData();

        LiveData<Integer> postalCode = Transformations.switchMap(addressInput, new Function<String, LiveData<Integer>>() {
            @Override
            public LiveData<Integer> apply(String address) {
                return getPostCode(address);
            }
        });

        postalCode.observe(this, new Observer<Integer>() {
            @Override
            public void onChanged(Integer s) {
                Log.d(TAG, "the postcode is:" + s.toString());
            }
        });

        addressInput.setValue("Los Angeles");
    }

    private LiveData<Integer> getPostCode(String address) {
        if(TextUtils.equals(address, "New York")){
            postCodeLiveData.setValue(10001);
        }else if(TextUtils.equals(address, "Los Angeles")){
            postCodeLiveData.setValue(90001);
        }
        return postCodeLiveData;
    }

}

打印如下:

csharp 复制代码
MyActivity     com.example.test   D  the postcode is:90001

观察多个LiveData数据

MediatorLiveData是LiveData的子类,可以用来观察多个LiveData的对象。只要其中任一个LiveData数据发生更改,就会触发MediatorLiveData的onChange()方法。

比如UI显示的数据来自于数据库或网络,你可以把从数据库获取的数据的LiveData和从网络获取的数据的LiveData都添加为MediatorLiveData对象的数据来源,代码如下:

java 复制代码
public class MyActivity extends AppCompatActivity {
    private static final String TAG = MyActivity.class.getSimpleName();
    private MutableLiveData postCodeLiveData =  new MutableLiveData<Integer>();

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        MutableLiveData<Integer> liveData1 = new MutableLiveData<>();
        MutableLiveData<Integer> liveData2 = new MutableLiveData<>();

        MediatorLiveData<Integer> liveDataMerger = new MediatorLiveData<>();
        liveDataMerger.addSource(liveData1, new Observer<Integer>() {
            @Override
            public void onChanged(Integer integer) {
                liveDataMerger.setValue(integer);
            }
        });
        
        liveDataMerger.addSource(liveData2, new Observer<Integer>() {
            @Override
            public void onChanged(Integer integer) {
                liveDataMerger.setValue(integer);
            }
        });

        liveDataMerger.observe(this, new Observer<Integer>() {
            @Override
            public void onChanged(Integer integer) {
                Log.d(TAG, "the value is:" + integer);
            }
        });

        liveData1.setValue(-1);
        liveData2.setValue(1);
    }

}

打印如下:

csharp 复制代码
MyActivity              com.example.test     D  the value is:-1
MyActivity              com.example.test     D  the value is:1

UI只需要观察MediatorLiveData就可以从两个数据源数据的更新。

源码分析

LiveData源码分析

我们从LiveData的observe()方法开始分析:

java 复制代码
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");  //如果不是主线程,抛异常
	
	    //LifecycleOwner是DESTROYED状态,直接返回
	    if (owner.getLifecycle().getCurrentState() == DESTROYED) {
	        // ignore
	        return;
	    }
	
	    //把owner和observer封装到LifecycleBoundObserver里
	    LifecycleBoundObserver wrapper = new LifecycleBoundObserver(owner, observer);
	    //observer和wrapper分别作为key和value添加到mObservers
	    ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
       //如果已经存在并且不是与当前LifecycleOwner绑定
	    if (existing != null && !existing.isAttachedTo(owner)) {
	        throw new IllegalArgumentException("Cannot add the same observer"
	                + " with different lifecycles");
	    }
       //如果已经存在并且与当前LifecycleOwner绑定
	    if (existing != null) {
	        return;
	    }
            
       //LifecycleBoundObserver作为owner生命周期的观察者
	    owner.getLifecycle().addObserver(wrapper);
	}
      
}

首先判断LifecycleOwner的状态,如果是DESTROYED状态就直接返回。然后把owner和observer封装到LifecycleBoundObserver中,LifecycleBoundObserver继承自ObserverWrapper并实现了LifecycleEventObserver接口,而LifecycleEventObserver接口又继承自LifecycleObserver接口。

上面代码第31行通过owner.getLifecycle().addObserver(wrapper)把LifecycleBoundObserver添加为owner的观察者。那么根据Lifecycle的特性,实现了LifecycleObserver接口并且加入LifecycleOwner的观察者就可以感知或获取LifecycleOwner的状态。

另外,observeForever()方法的代码如下:

java 复制代码
@MainThread
public void observeForever(@NonNull Observer<? super T> observer) {
    assertMainThread("observeForever");
    AlwaysActiveObserver wrapper = new AlwaysActiveObserver(observer);
    ObserverWrapper existing = mObservers.putIfAbsent(observer, wrapper);
    if (existing instanceof LiveData.LifecycleBoundObserver) {
        throw new IllegalArgumentException("Cannot add the same observer"
                + " with different lifecycles");
    }
    if (existing != null) {
        return;
    }
    wrapper.activeStateChanged(true);
}

和observe()方法类似,只不过添加的观察者一直是活跃状态,这意味着这个观察者会接收所有的事件并且不会自动移除,如果不用了你要手动调用removeObserver()方法移除。

LifecycleBoundObserver代码如下:

java 复制代码
public abstract class LiveData<T> {

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

        LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<? super T> observer) {
            super(observer);
            mOwner = owner;
        }
        
        @Override
        boolean shouldBeActive() {
            //mOwner为STARTED或RESUMED状态时,mOwner活跃
            return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
        }

        @Override
        public void onStateChanged(@NonNull LifecycleOwner source,
                @NonNull Lifecycle.Event event) {
            Lifecycle.State currentState = mOwner.getLifecycle().getCurrentState();
            //LifecycleOwner是DESTROYED状态,则移除观察者
            if (currentState == DESTROYED) {
                removeObserver(mObserver);
                return;
            }
            Lifecycle.State prevState = null;
            while (prevState != currentState) {
                prevState = currentState;
                activeStateChanged(shouldBeActive());
                currentState = mOwner.getLifecycle().getCurrentState();
            }
        }

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

        @Override
        void detachObserver() {
            mOwner.getLifecycle().removeObserver(this);
        }
    }
    
    private abstract class ObserverWrapper {
        final Observer<? super T> mObserver;
        boolean mActive;
        //默认为-1
        int mLastVersion = START_VERSION;

        ObserverWrapper(Observer<? super 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;
            changeActiveCounter(mActive ? 1 : -1);
            if (mActive) {
                //判断观察者是活跃状态,进行数据分发
                dispatchingValue(this);
            }
        }
    }
    
    @MainThread
    void changeActiveCounter(int change) {
        //previousActiveCount,以前活跃的观察者数量
        int previousActiveCount = mActiveCount;
        //mActiveCount,现在活跃的观察者数量
        mActiveCount += change;
        if (mChangingActiveState) {
            return;
        }
        mChangingActiveState = true;
        try {
            while (previousActiveCount != mActiveCount) {
                boolean needToCallActive = previousActiveCount == 0 && mActiveCount > 0;
                boolean needToCallInactive = previousActiveCount > 0 && mActiveCount == 0;
                previousActiveCount = mActiveCount;
                if (needToCallActive) {
                    onActive();//活跃的观察者数量 由0变为1
                } else if (needToCallInactive) {
                    onInactive();//活跃的观察者数量 由1变为0
                }
            }
        } finally {
            mChangingActiveState = false;
        }
    }
}

从上一篇文章Lifecyle的使用和源码解析中,我们了解到LifecycleOwner的生命周期发生变化时会分发对应的event事件,然后触发观察者的onStateChanged()方法回调。

这里onStateChanged()方法中先判断如果LifecycleOwner是DESTROYED状态,则移除观察者,LiveData自动移除观察者的特点就来源于此。接下来调用其父类ObserverWrapper的activeStateChanged()方法处理这个生命周期状态变化,shouldBeActive()的返回值作为参数,至少是STARTED或RESUMED状态,即为活跃状态。

这里解释一下,由于State枚举按照DESTROYED, INITIALIZED, CREATED, STARTED, RESUMED排列,isAtLeast(STARTED)就表示是STARTED或RESUMED状态。

mActiveCount是指LiveData的活跃观察者数量。活跃的观察者数量由0变为1、由1变为0会分别调用LiveData的onActive()、onInactive()方法。这就是前面提到的继承LiveData的回调方法。

最后判断如果观察者是活跃状态,调用dispatchingValue(this)进行数据分发,代码如下:

java 复制代码
public abstract class LiveData<T> {
    //用于判断是否正在执行dispatchingValue()方法
    private boolean mDispatchingValue;
    
    //用于判断当前分发是否失效
    //在分发期间添加了新观察者或分发被取消的情况,需要重新分发
    private boolean mDispatchInvalidated;

    private void dispatchingValue(@Nullable ObserverWrapper initiator) {
        //正在执行dispatchingValue(),直接return
        if (mDispatchingValue) {
            mDispatchInvalidated = true;
            return;
        }
        mDispatchingValue = true;
        do {
            mDispatchInvalidated = false;
            //initiator不为null,仅通知initiator
            if (initiator != null) {
                considerNotify(initiator);
                initiator = null;
            } 
            //initiator为null,通知mObservers上所有的观察者
            else {
                for (Iterator<Map.Entry<Observer<T>, ObserverWrapper>> iterator =
                        mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
                    considerNotify(iterator.next().getValue());
                    if (mDispatchInvalidated) {
                        break;
                    }
                }
            }
        } while (mDispatchInvalidated);
        mDispatchingValue = false;
    }
}

如果传入的参数initiator不为null,仅通知initiator这个观察者;如果initiator为null,将通过遍历mObservers拿到所有的ObserverWrapper。initiator啥时候为空呢?这里先留个疑问。继续看considerNotify()方法:

java 复制代码
public abstract class LiveData<T> {

    private void considerNotify(ObserverWrapper observer) {
        //观察者不活跃,直接return
        if (!observer.mActive) {
            return;
        }
        
        // 我们先检查observer.mActive作为判断入口
        // 即使observer.mActive为true,但是有可能LifecycleOwner现在已经不活跃了,
        // 只不过我们暂时还没有收到对应的event,所以这里还要检查LifecycleOwner是否活跃,
        // 发现LifecycleOwner不活跃了,再次调用activeStateChanged()方法,传入false
        if (!observer.shouldBeActive()) {
            observer.activeStateChanged(false);
            return;
        }
        if (observer.mLastVersion >= mVersion) {
            return;
        }
        observer.mLastVersion = mVersion;
        //noinspection unchecked
        observer.mObserver.onChanged((T) mData);
    }
}

代码最后一行的observer.mObserver就是我们调用LiveData的observe()方法传入的第2个参数,最后回调Observer接口的onChanged((T) mData)方法,将保存的数据mData传入,这样就实现了接口回调更新数据。

好了,看完了观察者处理数据的流程,那么LiveData什么时候会通知观察者呢?不用想,数据更新的时候肯定要通知观察者,在主线程更新数据需要我们自己调用setValue()方法,MutableLiveData的代码如下:

scala 复制代码
public class MutableLiveData<T> extends LiveData<T> {

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

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

MutableLiveData的setValue()方法会调用LiveData的的setValue()方法,代码如下:

java 复制代码
public abstract class LiveData<T> {

    private volatile Object mData;
    
    private int mVersion;
    
    static final int START_VERSION = -1;
    
    //创建值为value的LiveData 
    public LiveData(T value) {
        mData = value;
        mVersion = START_VERSION + 1;
    }

    //无参的LiveData 
    public LiveData() {
        mData = NOT_SET;
        mVersion = START_VERSION;
    }

    @MainThread
    protected void setValue(T value) {
        //必须在主线程执行
        assertMainThread("setValue");
        mVersion++;
        mData = value;
        dispatchingValue(null);
    }
}    

首先检查setValue()是否在主线程执行,不在主线程会报错。然后将mVersion加1,如果调用的是不带参数的LiveData的构造方法,这里mVersion变成0。再把value赋值给mData,然后调用dispatchingValue()方法,传入的参数是null,对应前面提到的initiator为null的场景,即遍历所有观察者进行分发回调。

而postValue()则可以在子线程执行,但是postValue()最终还是调用的setValue()方法,只不过会先把数据从子线程传递到主线程,代码如下:

java 复制代码
public abstract class LiveData<T> {

    final Object mDataLock = new Object();

    static final Object NOT_SET = new Object();

    private volatile Object mData;

    volatile Object mPendingData = NOT_SET;

    private final Runnable mPostValueRunnable = new Runnable() {

        @Override
        public void run() {
            Object newValue;

            synchronized (mDataLock) {
                newValue = mPendingData;
                mPendingData = NOT_SET;
            }
            setValue((T) newValue);
        }
    };

    protected void postValue(T value) {
        boolean postTask;

        synchronized (mDataLock) {
            postTask = mPendingData == NOT_SET;
            mPendingData = value;
        }
        if (!postTask) {
            return;
        }

        //切换到主线程执行setValue()
        ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
    }

}

第28行与第17行使用了同一把锁互斥执行,目的就是先通过postValue()方法把value赋值给mPendingData,然后再通过mPostValueRunnable的run()方法把mPendingData赋值给newValue,最后把newValue传给setValue()方法。

Transformations源码分析

最后看看map()方法的源码,switchMap()方法类似。

java 复制代码
public class Transformations {

    @MainThread
    public static <X, Y> LiveData<Y> map(
            @NonNull LiveData<X> source,
            @NonNull final Function<X, Y> mapFunction) {
            
        final MediatorLiveData<Y> result = new MediatorLiveData<>();
        result.addSource(source, new Observer<X>() {
            @Override
            public void onChanged(@Nullable X x) {
                //关注1
                result.setValue(mapFunction.apply(x));
            }
        });
        return result;
        
    }
    
}

map()方法里面新建了一个MediatorLiveData实例,然后调用了它的addSource()方法:

java 复制代码
public class MediatorLiveData<T> extends MutableLiveData<T> {

    private SafeIterableMap<LiveData<?>, Source<?>> mSources = new SafeIterableMap<>();

    @MainThread
    public <S> void addSource(@NonNull LiveData<S> source, @NonNull Observer<? super S> onChanged) {
        Source<S> e = new Source<>(source, onChanged);
        Source<?> existing = mSources.putIfAbsent(source, e);
        if (existing != null && existing.mObserver != onChanged) {
            throw new IllegalArgumentException(
                    "This source was already added with the different observer");
        }
        if (existing != null) {
            return;
        }
        
        //LiveData有活跃的观察者
        if (hasActiveObservers()) {
            e.plug();
        }
    }
    

    @MainThread
    public <S> void removeSource(@NonNull LiveData<S> toRemote) {
        Source<?> source = mSources.remove(toRemote);
        if (source != null) {
            source.unplug();
        }
    }
}

addSource()方法里面把liveData和Observer包装成Source,添加到mSources。最后判断如果有活跃的观察者,就调用Source的plug()方法。

java 复制代码
public class MediatorLiveData<T> extends MutableLiveData<T> {

    private static class Source<V> implements Observer<V> {
        final LiveData<V> mLiveData;
        final Observer<? super V> mObserver;
        int mVersion = START_VERSION;

        Source(LiveData<V> liveData, final Observer<? super V> observer) {
            mLiveData = liveData;
            mObserver = observer;
        }

        void plug() {
            mLiveData.observeForever(this);
        }

        void unplug() {
            mLiveData.removeObserver(this);
        }

        @Override
        public void onChanged(@Nullable V v) {
            if (mVersion != mLiveData.getVersion()) {
                mVersion = mLiveData.getVersion();
                mObserver.onChanged(v);
            }
        }
    }
    
}

这里plug()方法通过mLiveData.observeForever(this)添加自己为永远的观察者。这里为什么使用这样observeForever()方法呢?因为map()方法的目的是在任意情况下都要监听LiveData数据的改变来进行相应的操作。mLiveData数据改变时,代码中的onChanged()方法就会回调执行,onChange()方法又调用了mObserver.onChanged(v),最终执行关注1处的result.setValue(mapFunction.apply(x))。mapFunction.apply()是用来将X类型转成Y类型的,具体怎么转换需要你自己实现。所以最终返回的result是MediatorLiveData<Y>类型的LiveData并调用了其setValue()方法。这样,调用map()方法第1个参数的setValue()方法,转换后的LiveData的setValue()方法就会相应执行。

类关系图如下:

黏性事件

接下来分析一下LiveData的粘性事件

什么是粘性事件?发射的事件早于注册,可以收到注册之前发射的事件称为粘性事件。

LiveData内部通过一个整数mVersion来记录当前数据的版本号,如下所示:

java 复制代码
protected void setValue(T value) {	
    ...
    mVersion++;
    ...
}

当我们调用setValue()更新数据的时候,mVersion就会自增。

观察者的包装类ObserverWrapper内部也维护了一个版本号mLastVersion,它记录的是上一次回调的数据的版本,默认值为-1。

如果我们先调用setValue()方法,那么mVersion就会自增变为0,然后注册观察者,此时观察者内部维护的版本号mLastVersion为初始值-1。在considerNotify()方法中observer.mLastVersion >= mVersion就会不成立,onChange()方法会回调,观察者就会收到注册之前发射的数据。

java 复制代码
private void considerNotify(ObserverWrapper observer) {
    if (observer.mLastVersion >= mVersion) {
        return;
    }
    observer.mLastVersion = mVersion;
    observer.mObserver.onChanged((T) mData);
}

如何解决粘性问题呢?有以下两种方法:

  • 方法1.尽量避免这种情况,合理地设计Activity/Fragment的View Model,Fragment不要绑定Activity的View Model,要有自己独立的View Model,使得LiveData和Fragment同生共死。
  • 方法2.使用SingleLiveEvent解决粘性问题。 但这种方法有一个缺点,只能有一个观察者,要考虑自己业务的适用性。
  • 方法3.使用hook version的方法。这是没有办法的办法,但是功能适配性却最好,没有了粘性事件问题,这也是LiveDataBus源码中的方式。

方法2的机制是用AtomicBoolean记录setValue()的状态, 当setValue()被调用后,mPending被设置为true,mPending.compareAndSet(true, false)才返回true,observer.onChanged(t)才能执行,代码如下:

java 复制代码
public class SingleLiveEvent<T> extends MutableLiveData<T> {

    private final AtomicBoolean mPending = new AtomicBoolean(false);
    
    @Override
    public void observe(@NonNull LifecycleOwner owner, @NonNull final Observer<? super T> observer) {
        super.observe(owner, new Observer<T>() {
            @Override
            public void onChanged(@Nullable T t) {
                //CAS执行成功后才可以执行onChanged()方法
                //这样只有第一次setValue()后onChanged()方法才会执行
                if (mPending.compareAndSet(true, false)) {
                    observer.onChanged(t);
                }
            }
        });
    }
 
    @MainThread
    public void setValue(@Nullable T t) {
        //setValue()调用后将mPending设置为true
        mPending.set(true);
        super.setValue(t);
    }
 
    /**
     * Used for cases where T is Void, to make calls cleaner.
     */
    @MainThread
    public void call() {
        setValue(null);
    }
}

方法3通过在注册一个新的订阅者时把ObserverWrapper的mLastVersion设置成跟LiveData的 mVersion一致即可,代码如下:

java 复制代码
public class BusMutableLiveData<T> extends MutableLiveData<T> {
 
    private Map<Observer, Observer> observerMap = new HashMap<>();

    @Override
    public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<T> observer) {
        super.observe(owner, observer);
        try {
            hook(observer);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void observeForever(@NonNull Observer<T> observer) {
        if (!observerMap.containsKey(observer)) {
            observerMap.put(observer, new ObserverWrapper(observer));
        }
        super.observeForever(observerMap.get(observer));
    }

    @Override
    public void removeObserver(@NonNull Observer<T> observer) {
        Observer realObserver = null;
        if (observerMap.containsKey(observer)) {
            realObserver = observerMap.remove(observer);
        } else {
            realObserver = observer;
        }
        super.removeObserver(realObserver);
    }

    private void hook(@NonNull Observer<T> observer) throws Exception {
        //get wrapper's version
        Class<LiveData> classLiveData = LiveData.class;
        Field fieldObservers = classLiveData.getDeclaredField("mObservers");
        fieldObservers.setAccessible(true);
        Object objectObservers = fieldObservers.get(this);
        Class<?> classObservers = objectObservers.getClass();
        Method methodGet = classObservers.getDeclaredMethod("get", Object.class);
        methodGet.setAccessible(true);
        Object objectWrapperEntry = methodGet.invoke(objectObservers, observer);
        Object objectWrapper = null;
        if (objectWrapperEntry instanceof Map.Entry) {
            objectWrapper = ((Map.Entry) objectWrapperEntry).getValue();
        }
        if (objectWrapper == null) {
            throw new NullPointerException("Wrapper can not be bull!");
        }
        Class<?> classObserverWrapper = objectWrapper.getClass().getSuperclass();
        Field fieldLastVersion = classObserverWrapper.getDeclaredField("mLastVersion");
        fieldLastVersion.setAccessible(true);
        //get livedata's version
        Field fieldVersion = classLiveData.getDeclaredField("mVersion");
        fieldVersion.setAccessible(true);
        Object objectVersion = fieldVersion.get(this);
        //set wrapper's version
        fieldLastVersion.set(objectWrapper, objectVersion);
   }
}

感谢与参考

Livedata官方文档

相关推荐
x02415 天前
Android Room(SQLite) too many SQL variables异常
sqlite·安卓·android jetpack·1024程序员节
alexhilton18 天前
深入理解观察者模式
android·kotlin·android jetpack
Wgllss18 天前
花式高阶:插件化之Dex文件的高阶用法,极少人知道的秘密
android·性能优化·android jetpack
上官阳阳21 天前
使用Compose创造有趣的动画:使用Compose共享元素
android·android jetpack
沐言人生25 天前
Android10 Framework—Init进程-15.属性变化控制Service
android·android studio·android jetpack
IAM四十二1 个月前
Android Jetpack Core
android·android studio·android jetpack
王能1 个月前
Kotlin真·全平台——Kotlin Compose Multiplatform Mobile(kotlin跨平台方案、KMP、KMM)
android·ios·kotlin·web·android jetpack·kmp·kmm
alexhilton1 个月前
让Activity更加优雅地跳转
android·kotlin·android jetpack
沐言人生1 个月前
Android10 Framework—Init进程-11.客户端操作属性
android·android studio·android jetpack
沐言人生1 个月前
Android10 Framework—Init进程-9.服务端属性值初始化
android·android studio·android jetpack