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官方文档

相关推荐
一航jason10 天前
Android Jetpack Compose 现有Java老项目集成使用compose开发
android·java·android jetpack
帅次12 天前
Android CoordinatorLayout:打造高效交互界面的利器
android·gradle·android studio·rxjava·android jetpack·androidx·appcompat
IAM四十二14 天前
Jetpack Compose State 你用对了吗?
android·android jetpack·composer
Wgllss15 天前
那些大厂架构师是怎样封装网络请求的?
android·架构·android jetpack
x0241 个月前
Android Room(SQLite) too many SQL variables异常
sqlite·安卓·android jetpack·1024程序员节
alexhilton1 个月前
深入理解观察者模式
android·kotlin·android jetpack
Wgllss1 个月前
花式高阶:插件化之Dex文件的高阶用法,极少人知道的秘密
android·性能优化·android jetpack
上官阳阳1 个月前
使用Compose创造有趣的动画:使用Compose共享元素
android·android jetpack
沐言人生1 个月前
Android10 Framework—Init进程-15.属性变化控制Service
android·android studio·android jetpack
IAM四十二1 个月前
Android Jetpack Core
android·android studio·android jetpack