欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

詳解Android JetPack之LiveData的工作原理

 更新時(shí)間:2021年03月23日 09:24:10   作者:靜靜的小貓  
這篇文章主要介紹了詳解Android JetPack之LiveData的工作原理,幫助大家更好的理解和學(xué)習(xí)使用Android開發(fā),感興趣的朋友可以了解下

前言

本篇文章主要講解LiveData工作的原理,如果還不知道LiveData如何用的話,請(qǐng)參考官方文檔。 LiveData的講解涉及到了Lifecycle的知識(shí),如果你還不了解LifeCycle,請(qǐng)參考文檔LifeCycle介紹。

介紹

LiveData是一個(gè)數(shù)據(jù)持有類,它可以通過添加觀察者被其他組件觀察其變更。不同于普通的觀察者,它最重要的特性就是遵從應(yīng)用程序的生命周期,如在Activity中如果數(shù)據(jù)更新了但Activity已經(jīng)是destroy狀態(tài),LivaeData就不會(huì)通知Activity(observer)。當(dāng)然。LiveData的優(yōu)點(diǎn)還有很多,如不會(huì)造成內(nèi)存泄漏等。

LiveData通常會(huì)配合ViewModel來使用,ViewModel負(fù)責(zé)觸發(fā)數(shù)據(jù)的更新,更新會(huì)通知到LiveData,然后LiveData再通知活躍狀態(tài)的觀察者。

原理分析

下面直接看代碼:

public class UserProfileViewModel extends ViewModel {
 private String userId;
 private MutableLiveData<User> user;
 private UserRepository userRepo;

 public void init(String userId) {
  this.userId = userId;
  userRepo = new UserRepository();
  user = userRepo.getUser(userId);
 }

 public void refresh(String userId) {
  user = userRepo.getUser(userId);
 }

 public MutableLiveData<User> getUser() {
  return user;
 }

}

上面UserProfileViewModel內(nèi)部持有 UserRepository 中 MutableLiveData的引用,并且提供了獲取 MutableLiveData 的方法 getUser(),UserRepository 負(fù)責(zé)從網(wǎng)絡(luò)或數(shù)據(jù)庫中獲取數(shù)據(jù)并封裝成 MutableLiveData 然后提供給 ViewModel。

我們?cè)?UserProfileFragment 中為 MutableLiveData 注冊(cè)觀察者,如下:

@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
 super.onActivityCreated(savedInstanceState);
 String userId = getArguments().getString(UID_KEY);
 viewModel = ViewModelProviders.of(this).get(UserProfileViewModel.class);
 viewModel.init(userId);
 //標(biāo)注1
 viewModel.getUser().observe(UserProfileFragment.this, new Observer<User>() {
  @Override
  public void onChanged(@Nullable User user) {
   if (user != null) {
    tvUser.setText(user.toString());
   }
  }
 });
}

看標(biāo)注1處,viewModel.getUser()獲取到 MutableLiveData 也就是我們的 LiveData,然后調(diào)用 LiveData的observer方法,并把UserProfileFragment作為參數(shù)傳遞進(jìn)去。observer() 方法就是我們分析的入口了,接下來我們看LiveData的observer()方法都做了什么:

@MainThread
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<T> observer) {
 //標(biāo)注1
 if (owner.getLifecycle().getCurrentState() == DESTROYED) {
  // ignore
  return;
 }
 //標(biāo)注2
 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);
}

可以看到,UserProfileFragment 是作為 LifeCycleOwner 參數(shù)傳進(jìn)來的,如果你的support包版本大于等于26.1.0,support包中的 Fragment 會(huì)默認(rèn)繼承自 LifecycleOwner,而 LifecycleOwner 可獲取到該組件的 LifeCycle,也就知道了 UserProfileFragment 組件的生命周期(在這里默認(rèn)大家已經(jīng)了解過LifeCycle了)。

看標(biāo)注1處,如果我們的 UserProfileFragment 組件已經(jīng)是destroy狀態(tài)的話,將直接返回,不會(huì)被加入觀察者行列。如果不是destroy狀態(tài),就到標(biāo)注2處,新建一個(gè) LifecycleBoundObserver 將我們的 LifecycleOwner 和 observer保存起來,然后調(diào)用 mObservers.putIfAbsent(observer, wrapper) 將observer和wrapper分別作為key和value存入Map中,putIfAbsent()方法會(huì)判斷如果 value 已經(jīng)能夠存在,就返回,否則返回null。 如果返回existing為null,說明以前沒有添加過這個(gè)觀察者,就將 LifecycleBoundObserver 作為 owner 生命周期的觀察者,也就是作為 UserProfileFragment 生命周期的觀察者。

我們看下LifecycleBoundObserver 源碼:

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

 LifecycleBoundObserver(@NonNull LifecycleOwner owner, Observer<T> observer) {
  super(observer);
  mOwner = owner;
 }

 @Override
 boolean shouldBeActive() {
  return mOwner.getLifecycle().getCurrentState().isAtLeast(STARTED);
 }

 @Override
 public void onStateChanged(LifecycleOwner source, Lifecycle.Event event) {
  if (mOwner.getLifecycle().getCurrentState() == DESTROYED) {
   removeObserver(mObserver);
   return;
  }
  activeStateChanged(shouldBeActive());
 }

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

 @Override
 void detachObserver() {
  mOwner.getLifecycle().removeObserver(this);
 }
}

代碼并不多,LifecycleBoundObserver 繼承自 ObserverWrapper 并實(shí)現(xiàn)了 GenericLifecycleObserver接口,而 GenericLifecycleObserver 接口又繼承自 LifecycleObserver 接口,那么根據(jù) Lifecycle 的特性,實(shí)現(xiàn)了LifecycleObserver接口并且加入 LifecycleOwner 的觀察者里就可以感知或主動(dòng)獲取 LifecycleOwner 的狀態(tài)。

好了,看完了觀察者,那么我們的LiveData什么時(shí)候會(huì)通知觀察者呢?不用想,肯定是數(shù)據(jù)更新的時(shí)候,而數(shù)據(jù)的更新是我們代碼自己控制的,如請(qǐng)求網(wǎng)絡(luò)返回User信息后,我們會(huì)主動(dòng)將User放入MutableLiveData中,這里我在UserRepository中直接模擬網(wǎng)絡(luò)請(qǐng)求如下:

public class UserRepository {
 final MutableLiveData<User> data = new MutableLiveData<>();

 public MutableLiveData<User> getUser(final String userId) {
  if ("xiasm".equals(userId)) {
   data.setValue(new User(userId, "夏勝明"));
  } else if ("123456".equals(userId)) {
   data.setValue(new User(userId, "哈哈哈"));
  } else {
   data.setValue(new User(userId, "unknow"));
  }
  return data;
 }
}

當(dāng)調(diào)用getUser()方法的時(shí)候,我們調(diào)用MutableLiveData的setValue()方法將數(shù)據(jù)放入LiveData中,這里MutableLiveData實(shí)際上就是繼承自LiveData,沒有什么特別:

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

setValue()在放入U(xiǎn)ser的時(shí)候必須在主線程,否則會(huì)報(bào)錯(cuò),而postValue則沒有這個(gè)檢查,而是會(huì)把數(shù)據(jù)傳入到主線程。我們直接看setValue()方法:

@MainThread
protected void setValue(T value) {
 assertMainThread("setValue");
 mVersion++;
 mData = value;
 dispatchingValue(null);
}

首先調(diào)用assertMainThread()檢查是否在主線程,接著將要更新的數(shù)據(jù)賦給mData,然后調(diào)用 dispatchingValue()方法并傳入null,將數(shù)據(jù)分發(fā)給各個(gè)觀察者,如我們的 UserProfileFragment???dispatchingValue()方法實(shí)現(xiàn):

private void dispatchingValue(@Nullable ObserverWrapper initiator) {
 if (mDispatchingValue) {
  mDispatchInvalidated = true;
  return;
 }
 mDispatchingValue = true;
 do {
  mDispatchInvalidated = false;
  //標(biāo)注1
  if (initiator != null) {
   considerNotify(initiator);
   initiator = null;
  } else {
   //標(biāo)注2
   for (Iterator<Map.Entry<Observer<T>, ObserverWrapper>> iterator =
     mObservers.iteratorWithAdditions(); iterator.hasNext(); ) {
    considerNotify(iterator.next().getValue());
    if (mDispatchInvalidated) {
     break;
    }
   }
  }
 } while (mDispatchInvalidated);
 mDispatchingValue = false;
}

從標(biāo)注1可以看出,dispatchingValue()參數(shù)傳null和不傳null的區(qū)別就是如果傳null將會(huì)通知所有的觀察者,反之僅僅通知傳入的觀察者。我們直接看標(biāo)注2,通知所有的觀察者通過遍歷 mObservers ,將所有的 ObserverWrapper 拿到,實(shí)際上就是我們上面提到的 LifecycleBoundObserver,通知觀察者調(diào)用considerNotify()方法,這個(gè)方法就是通知的具體實(shí)現(xiàn)了。

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;
 //noinspection unchecked
 observer.mObserver.onChanged((T) mData);
}

如果觀察者不是活躍狀態(tài),將不會(huì)通知此觀察者,看最后一行,observer.mObserver.onChanged((T) mData),observer.mObserver就是我們調(diào)用LiveData的observer()方法傳入的 Observer,然后調(diào)用 Observer 的 onChanged((T) mData)方法,將保存的數(shù)據(jù)mData傳入,也就實(shí)現(xiàn)了更新。在看下我們實(shí)現(xiàn)的Observer:

viewModel.getUser().observe(UserProfileFragment.this, new Observer<User>() {
 @Override
 public void onChanged(@Nullable User user) {
  if (user != null) {
   tvUser.setText(user.toString());
  }
 }
});

如果哪個(gè)控件要根據(jù)user的變更而及時(shí)更新,就在onChanged()方法里處理就可以了。到這里,LiveData已經(jīng)能夠分析完了,其實(shí)LiveData的實(shí)現(xiàn)還是要依賴于Lifecycle。

以上就是詳解Android JetPack之LiveData的工作原理的詳細(xì)內(nèi)容,更多關(guān)于Android JetPack之LiveData的工作原理的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Android 開發(fā)照相功能實(shí)例詳解

    Android 開發(fā)照相功能實(shí)例詳解

    這篇文章主要介紹了Android 開發(fā)照相功能實(shí)例詳解的相關(guān)資料,需要的朋友可以參考下
    2017-04-04
  • Android 使用Path實(shí)現(xiàn)涂鴉功能

    Android 使用Path實(shí)現(xiàn)涂鴉功能

    到月底了最近比較空閑,今天抽空給大家實(shí)現(xiàn)一個(gè)涂鴉效果,會(huì)分幾步實(shí)現(xiàn),這里有一個(gè)重要的知識(shí)點(diǎn)就是圖層,要理解這個(gè)。下面先從簡(jiǎn)單的說起,一起看看代碼吧
    2016-12-12
  • Android開發(fā)之CheckBox的簡(jiǎn)單使用與監(jiān)聽功能示例

    Android開發(fā)之CheckBox的簡(jiǎn)單使用與監(jiān)聽功能示例

    這篇文章主要介紹了Android開發(fā)之CheckBox的簡(jiǎn)單使用與監(jiān)聽功能,結(jié)合簡(jiǎn)單實(shí)例形式分析了Android使用CheckBox控件的布局與功能實(shí)現(xiàn)技巧,需要的朋友可以參考下
    2017-07-07
  • Kotlin原理詳析之拓展函數(shù)

    Kotlin原理詳析之拓展函數(shù)

    kotlin中的擴(kuò)展函數(shù),實(shí)際上是在自己的類中添加了一個(gè)static final方法,將需要擴(kuò)展的類,在使用的時(shí)候作為第一個(gè)參數(shù)傳入方法中,然后使用,這篇文章主要給大家介紹了關(guān)于Kotlin原理詳析之拓展函數(shù)的相關(guān)資料,需要的朋友可以參考下
    2022-01-01
  • Android自定義View繪制居中文本

    Android自定義View繪制居中文本

    這篇文章主要為大家詳細(xì)介紹了Android自定義View繪制居中文本,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-06-06
  • android使用Textview實(shí)現(xiàn)伸縮效果

    android使用Textview實(shí)現(xiàn)伸縮效果

    這篇文章主要為大家詳細(xì)介紹了android使用Textview實(shí)現(xiàn)伸縮效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-11-11
  • Android中src和background的區(qū)別詳解

    Android中src和background的區(qū)別詳解

    這篇文章主要介紹了Android中src和background的區(qū)別詳解的相關(guān)資料,需要的朋友可以參考下
    2016-09-09
  • Android實(shí)現(xiàn)拍照、選擇圖片并裁剪圖片功能

    Android實(shí)現(xiàn)拍照、選擇圖片并裁剪圖片功能

    這篇文章主要為大家詳細(xì)介紹了Android實(shí)現(xiàn)拍照、選擇圖片并裁剪圖片功能的相關(guān)資料,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-05-05
  • android使用ItemDecoration給RecyclerView 添加水印

    android使用ItemDecoration給RecyclerView 添加水印

    本篇文章主要介紹了android使用ItemDecoration給RecyclerView 添加水印,介紹了自定義Drawable來完成水印圖片和使用ItemDecoration來布局水印,有興趣的可以了解一下。
    2017-02-02
  • Android編程實(shí)現(xiàn)自動(dòng)檢測(cè)版本及自動(dòng)升級(jí)的方法

    Android編程實(shí)現(xiàn)自動(dòng)檢測(cè)版本及自動(dòng)升級(jí)的方法

    這篇文章主要介紹了Android編程實(shí)現(xiàn)自動(dòng)檢測(cè)版本及自動(dòng)升級(jí)的方法,涉及Android版本檢測(cè),匹配,下載及自動(dòng)安裝等技巧,需要的朋友可以參考下
    2016-01-01

最新評(píng)論