发现问题
初识livedata,想在项目中用着试试,于是尝试了个demo:
- 先定义retrofit接口ApiLibService:用来获取此接口(www.weather.com.cn/data/cityin…) 的天气数据
interface ApiLibService {
@Headers("Content-Type: application/json", "Content-Encoding: gzip")
@GET("/data/cityinfo/101010100.html")
fun weather(): LiveData<ApiResponse<WeatherResult>>
}
ApiResponse是对返回结果的封装,本身是个sealed类
- 用repository类引用他:
class HomeRepository @Inject constructor(
private val apiLibService: ApiLibService
){
fun getWeather(): LiveData<Resource<WeatherResult>> = apiLibService.weather().asResource()
}
ApiLibService是由dagger注入
asResource为自定义LiveData扩展方法,其作用是将ApiResponse封装转化为Resoure封装,Resouce维护了success,error和loading三个状态
3.再由viewmodel调用repository,在fragment中调用viewmodel
class HomeViewModel @Inject constructor(
private val repository: HomeRepository
) : ViewModel(){
private val _textNet = MutableLiveData<String>()
val textNet = _textNet
fun getWeather() {
repository.getWeather().map {
if(it.status == Status.SUCCESS) {
val data = it.data?.weatherinfo
_textNet.postValue(data.toString())
} else {
_textNet.postValue(it.message)
}
}
}
}
class HomeFragment : Fragment() , Injectable {
private lateinit var homeViewModel: HomeViewModel
@Inject
lateinit var factory: MyViewModelFactory
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
homeViewModel = ViewModelProviders.of(this, factory).get(HomeViewModel::class.java)
}
override fun onActivityCreated(savedInstanceState: Bundle?) {
homeViewModel.textNet.observe(viewLifecycleOwner, Observer {
text_home.text = "$it"
})
homeViewModel.getWeather()
}
}
repository也同样是dagger的注入,map为Transformations中的map方法
由fragment调用viewmodel的getWeather方法,通常的思路就是能触发epository.getWeather()并一步步执行下去,返回resource结果,由_textNet这个livedata通知到fragment的text_home更新
但事实是什么都没发生
说明livedata必然有observer才会触发:
于是这样修改:
fun getWeather(lifecycleOwner : LifecycleOwner) {
repository.getWeather().observe(lifecycleOwner, Observer {
if(it.status == Status.SUCCESS) {
val data = it.data?.weatherinfo
_textNet.postValue(data.toString())
} else {
_textNet.postValue(it.message)
}
})
}
调用则改为:
homeViewModel.getWeather(lifecycleOwner = viewLifecycleOwner)
这样就正常了
详细代码可以移步这里:github.com/robinfjb/An…
源码探究:
首先来看下observe方法:
public abstract class LiveData<T> {
@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<? super T> observer) {
assertMainThread("observe");
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);
}
}
生成一个新的LifecycleBoundObserver(ObserverWapper)对象,将observer为key,ObserverWapper对象为value放在名为mObservers的map中,并将其加入到生命周期观察中去
分析下LifecycleBoundObserver :
class LifecycleBoundObserver extends ObserverWrapper implements LifecycleEventObserver {
...
@Override
boolean shouldBeActive() {
return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
}
@Override
public void onStateChanged(@NonNull LifecycleOwner source,
@NonNull Lifecycle.Event event) {
if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
removeObserver(mObserver);
return;
}
activeStateChanged(shouldBeActive());
}
...
}
实现了LifecycleEventObserver接口,一旦生命周期发生变化,则会调用onStateChanged方法,看下activeStateChanged的实现,在父类ObserverWrapper中:
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);
}
}
最后一句代码,如果mActive=true则会调用dispatchingValue方法,mActive在LifecycleBoundObserver中的实现为lifecycle值为STARTED或以上,换一句话说,只要是组件调用onStart或者onResume就会触发
dispatchingValue的代码:
@SuppressWarnings("WeakerAccess") /* synthetic access */
void dispatchingValue(@Nullable ObserverWrapper initiator) {
...
do {
mDispatchInvalidated = false;
if (initiator != null) {
considerNotify(initiator);
initiator = null;
} else {
for (Iterator<Map.Entry<Observer<? super T>, ObserverWrapper>> iterator =
mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
considerNotify(iterator.next().getValue());
if (mDispatchInvalidated) {
break;
}
}
}
} while (mDispatchInvalidated);
...
}
又会调用LiveData的considerNotify方法:
private void considerNotify(ObserverWrapper observer) {
if (!observer.mActive) {
return;
}
// Check latest state b4 dispatch. Maybe it changed state but we didn't get the event yet.
//
// we still first check observer.active to keep it as the entrance for events. So even if
// the observer moved to an active state, if we've not received that event, we better not
// notify for a more predictable notification order.
if (!observer.shouldBeActive()) {
observer.activeStateChanged(false);
return;
}
if (observer.mLastVersion >= mVersion) {
return;
}
observer.mLastVersion = mVersion;
observer.mObserver.onChanged((T) mData);
}
这里又会检查下shouldBeActive方法
这里有个关键点,会比较版本号,如果版本号没更新则不会通知onChanged
mVerison在LiveData有参构造中设置为0,无参构造函数中设置为-1,在setValue中自增+1
static final int START_VERSION = -1;
public LiveData(T value) {
...
mVersion = START_VERSION + 1;
}
public LiveData() {
...
mVersion = START_VERSION;
}
@MainThread
protected void setValue(T value) {
assertMainThread("setValue");
mVersion++;
mData = value;
dispatchingValue(null);
}
同样,调用setValue也会触发dispatchingValue,但此处传入的参数是null,dispatchingValue中会遍历mObservers找到对应的ObserverWapper,所以如果没有注册过ObserverWapper,则不会发生任何事
线程切换
在上述例子中,我们通过LiveDataCallAdapter来实现了retrofit的Call转LiveData:
lass LiveDataCallAdapter<R>(private val responseType: Type) :
CallAdapter<R, LiveData<ApiResponse<R>>> {
override fun responseType() = responseType
override fun adapt(call: Call<R>): LiveData<ApiResponse<R>> {
return object : LiveData<ApiResponse<R>>() {
private var started = AtomicBoolean(false)
override fun onActive() {
super.onActive()
if (started.compareAndSet(false, true)) {
call.enqueue(object : Callback<R> {
override fun onResponse(call: Call<R>, response: Response<R>) {
postValue(ApiResponse.create(response))
}
override fun onFailure(call: Call<R>, throwable: Throwable) {
postValue(ApiResponse.create(throwable))
}
})
}
}
}
}
}
在此调用的是LiveData中的postValue方法,将net的线程转为main线程
看下postValue中如何实现线程切换:
protected void postValue(T value) {
boolean postTask;
synchronized (mDataLock) {
postTask = mPendingData == NOT_SET;
mPendingData = value;
}
if (!postTask) {
return;
}
ArchTaskExecutor.getInstance().postToMainThread(mPostValueRunnable);
}
代码很简单,用ArchTaskExecutor类来实现postToMainThread,这个类是androidx包下的多线程包装类, postToMainThread的实现主要是具有MainLooper的Handler来实现,
mPostValueRunnable:
private final Runnable mPostValueRunnable = new Runnable() {
@SuppressWarnings("unchecked")
@Override
public void run() {
Object newValue;
synchronized (mDataLock) {
newValue = mPendingData;
mPendingData = NOT_SET;
}
setValue((T) newValue);
}
};
用同一个对象锁mDataLock实现数据同步,并将mPendingData置为初始状态,保证只运行一次,最终调用setValue方法
综上所诉,LiveData的代码实现还是比较简单明朗,LiveData 的特点在于它是一个可感知生命周期的观察者模式,重点是观察者模式与普通思维的不同