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

Android 基于MediatorLiveData實(shí)現(xiàn)紅點(diǎn)的統(tǒng)一管理

 更新時(shí)間:2021年04月07日 09:21:13   作者:入魔的冬瓜  
這篇文章主要介紹了Android 基于MediatorLiveData實(shí)現(xiàn)紅點(diǎn)的統(tǒng)一管理,幫助大家更好的理解和學(xué)習(xí)使用Android,感興趣的朋友可以了解下

背景

小紅點(diǎn)在各個(gè)App內(nèi)隨處可見,并且隨著需求的不斷迭代,需要展示小紅點(diǎn)的需求越來越多。

  • 不同需求之間,紅點(diǎn)顯示可能有沖突。
  • 不同頁(yè)面之間,紅點(diǎn)顯示會(huì)有關(guān)聯(lián)。
  • 同一個(gè)紅點(diǎn),可能顯示成數(shù)字樣式,紅點(diǎn)樣式,文案樣式。

這個(gè)時(shí)候,如果沒有對(duì)紅點(diǎn)的展示邏輯做一個(gè)統(tǒng)一的抽象和管理的話,就會(huì)感覺很復(fù)雜,后續(xù)也不太好維護(hù)。

本文會(huì)基于MediatorLiveData,實(shí)現(xiàn)對(duì)紅點(diǎn)的統(tǒng)一管理。

需求分析

這里舉個(gè)例子,常見的紅點(diǎn)場(chǎng)景,類似qq首頁(yè)左上角紅點(diǎn)的顯示。

  1. 4個(gè)頁(yè)面,由首頁(yè)進(jìn)入到隱私保護(hù)指引頁(yè)面,都有相應(yīng)的紅點(diǎn)View顯示,去引導(dǎo)用戶進(jìn)入到最里面的"隱私保護(hù)指引"頁(yè)面。
  2. 當(dāng)用戶點(diǎn)擊紅點(diǎn),進(jìn)入到"隱私保護(hù)指引"頁(yè)面后,隱私保護(hù)指引對(duì)應(yīng)的紅點(diǎn)就會(huì)消失,同時(shí)會(huì)觸發(fā)上級(jí)頁(yè)面的紅點(diǎn)刷新。

思路分析

樹形模型

一個(gè)App的頁(yè)面本身就是分級(jí)的,對(duì)于頁(yè)面的訪問路徑本質(zhì)上就是個(gè)樹型結(jié)構(gòu)。 整體的實(shí)現(xiàn)思路是用樹形模型去管理不同頁(yè)面的紅點(diǎn)。

  • 每個(gè)小紅點(diǎn)就是一個(gè)樹的節(jié)點(diǎn),父節(jié)點(diǎn)的小紅點(diǎn)是否顯示,取決于它的子節(jié)點(diǎn)的并集結(jié)果。
  • 同一個(gè)頁(yè)面中的不同紅點(diǎn)。在樹中是同一個(gè)層級(jí),屬于兄弟關(guān)系,互相獨(dú)立。
  • 子節(jié)點(diǎn)的狀態(tài)變化,會(huì)遞歸地去觸發(fā)父節(jié)點(diǎn)的狀態(tài)變化。

具體代碼實(shí)現(xiàn)

那對(duì)應(yīng)的代碼應(yīng)該如何實(shí)現(xiàn)呢,難道真的要手動(dòng)自己實(shí)現(xiàn)一棵樹?也不是不行,就是感覺有點(diǎn)小麻煩的樣子。 下面進(jìn)入正題。

MediatorLiveData

官方提供了MediatorLiveData。

  • 通過addSource方法,可以監(jiān)聽另一個(gè)LiveData的數(shù)據(jù)變化
  • 本身就是一個(gè)LiveData,可以被其他Observer觀察

這兩個(gè)特點(diǎn),剛好滿足我們的需求實(shí)現(xiàn)。比如MediatorLiveData A觀察 MediatorLiveData B,MediatorLiveData B觀察 MediatorLiveData C 和MediatorLiveData D。并且被觀察的LiveData發(fā)生變化,作為觀察的LiveData都能收到通知。

通過管理多個(gè)LiveData之間的關(guān)系,這樣就可以間接實(shí)現(xiàn)了一棵樹的模型。

public class MediatorLiveData<T> extends MutableLiveData<T> {
  private SafeIterableMap<LiveData<?>, Source<?>> mSources = new SafeIterableMap<>();

  
  public <S> void addSource(@NonNull LiveData<S> source, @NonNull Observer<? super S> onChanged) {
    //使用Source包一下
    Source<S> e = new Source<>(source, onChanged);
    Source<?> existing = mSources.putIfAbsent(source, e);
    if (hasActiveObservers()) {
      e.plug();
    }
  }

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

RedPointManager

  • 這里的實(shí)現(xiàn),封裝成一個(gè)單例RedPointManager,暴露相應(yīng)的紅點(diǎn)數(shù)據(jù)給外部。
  • LiveData數(shù)據(jù)驅(qū)動(dòng):RedPointManager內(nèi)包含了多個(gè)LiveData,不同頁(yè)面的紅點(diǎn)View可以通過觀察對(duì)應(yīng)的LiveData,來驅(qū)動(dòng)自身的視圖變化。
  • 父節(jié)點(diǎn)使用MediatorLiveData,觀察相應(yīng)的子節(jié)點(diǎn)LiveData。 葉子節(jié)點(diǎn)定義成普通的LiveData就行了,因?yàn)椴恍枰^察其他對(duì)象了。

/**
 * 基于MediatorLiveData,實(shí)現(xiàn)樹形紅點(diǎn)管理
 */
class RedPointManager : IRedPointManager {

  companion object {
    val TAG = "RedPointManager"

    @JvmStatic
    val instance: IRedPointManager by lazy(mode = LazyThreadSafetyMode.SYNCHRONIZED) {
      RedPointManager()
    }
  }

  override val liveDataA = MediatorLiveData<Boolean>()
  override val liveDataB1 = MediatorLiveData<Boolean>()
  override val liveDataB2 = MutableLiveData<Boolean>()
  override val liveDataC1 = MutableLiveData<Boolean>()
  override val liveDataC2 = MutableLiveData<Boolean>()

  init {
    Log.d(TAG, "RedPointManager init")
    /**
     * 構(gòu)建樹型關(guān)系。按路徑層級(jí),進(jìn)行觀察。一般外部只需要改動(dòng)最低層的紅點(diǎn)對(duì)應(yīng)的LiveData,頂部的LiveData就會(huì)自動(dòng)改變
     */
    liveDataA.addSource(liveDataB1, Observer {
      liveDataA.postValue(liveDataB1.isTrue() || liveDataB2.isTrue())
    })
    liveDataA.addSource(liveDataB2, Observer {
      liveDataA.postValue(liveDataB1.isTrue() || liveDataB2.isTrue())
    })

    liveDataB1.addSource(liveDataC1, Observer {
      liveDataB1.postValue(liveDataC1.isTrue() || liveDataC2.isTrue())
    })
    liveDataB1.addSource(liveDataC2, Observer {
      liveDataB1.postValue(liveDataC1.isTrue() || liveDataC2.isTrue())
    })
  }

  override fun testChangeDataC1(show: Boolean) {
    liveDataC1.postValue(show)
    Log.d(TAG, "testChangeDataC1: $show")
  }
}

/**
 * 定義接口
 * 提供只讀的屬性,提供修改liveData的方法
 */
interface IRedPointManager {
  val liveDataA: LiveData<Boolean>
  val liveDataB1: LiveData<Boolean>
  val liveDataB2: LiveData<Boolean>
  val liveDataC1: LiveData<Boolean>
  val liveDataC2: LiveData<Boolean>

  fun testChangeDataC1(show: Boolean)
}

驗(yàn)證刷新邏輯

一般情況下,只需要改動(dòng)葉子節(jié)點(diǎn)的紅點(diǎn)對(duì)應(yīng)的LiveData,父節(jié)點(diǎn)的LiveData就會(huì)自動(dòng)改變。 基于上述代碼,調(diào)用testChangeDataC1方法后,監(jiān)聽LiveData并輸出日志。

  private fun testRedPointManager() {
    RedPointManager.instance.liveDataA.observe(this, Observer {
      Log.d(TAG, "liveDataA: $it")
    })
    RedPointManager.instance.liveDataB1.observe(this, Observer {
      Log.d(TAG, "liveDataB1: $it")
    })
    RedPointManager.instance.liveDataB2.observe(this, Observer {
      Log.d(TAG, "liveDataB2: $it")
    })
    RedPointManager.instance.liveDataC1.observe(this, Observer {
      Log.d(TAG, "liveDataC1: $it")
    })
    RedPointManager.instance.liveDataC2.observe(this, Observer {
      Log.d(TAG, "liveDataC2: $it")
    })
    RedPointManager.instance.testChangeDataC1(true)
  }
  
 //從輸出日志可以發(fā)現(xiàn),底層的liveDataC1發(fā)生改變,觸發(fā)頂層的liveDataB1發(fā)生改變。liveDataB1的變化,也觸發(fā)了liveDataA發(fā)生改變。
RedPointManager init
testChangeDataC1: true
liveDataC1: true
lveDataB1: true
liveDataA: true

總結(jié)

到這里就結(jié)束了,App端內(nèi)實(shí)現(xiàn)紅點(diǎn)的統(tǒng)一管理,如果有類似的場(chǎng)景,可以用這種思路去實(shí)現(xiàn)。 上面的例子比較簡(jiǎn)單,更復(fù)雜的場(chǎng)景,應(yīng)該也是可以基于上面的方案進(jìn)行改造一下的。

以上就是Android 基于MediatorLiveData實(shí)現(xiàn)紅點(diǎn)的統(tǒng)一管理的詳細(xì)內(nèi)容,更多關(guān)于MediatorLiveData實(shí)現(xiàn)紅點(diǎn)的統(tǒng)一管理的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Android操作系統(tǒng)介紹之11種傳感器

    Android操作系統(tǒng)介紹之11種傳感器

    Android是一種基于Linux的自由及開放源代碼的操作系統(tǒng),主要使用于移動(dòng)設(shè)備,如智能手機(jī)和平板電腦,Android是一種基于Linux的自由及開放源代碼的操作系統(tǒng),主要使用于移動(dòng)設(shè)備,如智能手機(jī)和平板電腦,非常不錯(cuò),具有參考借鑒價(jià)值,感興趣的朋友一起學(xué)習(xí)吧
    2016-07-07
  • Android仿淘寶商品詳情頁(yè)

    Android仿淘寶商品詳情頁(yè)

    這篇文章主要為大家詳細(xì)介紹了Android仿淘寶商品詳情頁(yè),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-10-10
  • Android開發(fā)基于ScrollView實(shí)現(xiàn)的漸變導(dǎo)航欄效果示例

    Android開發(fā)基于ScrollView實(shí)現(xiàn)的漸變導(dǎo)航欄效果示例

    這篇文章主要介紹了Android開發(fā)基于ScrollView實(shí)現(xiàn)的漸變導(dǎo)航欄效果,涉及ScrollView事件響應(yīng)及元素屬性動(dòng)態(tài)操作相關(guān)實(shí)現(xiàn)技巧,需要的朋友可以參考下
    2017-12-12
  • ObjectAnimator屬性動(dòng)畫源碼分析篇

    ObjectAnimator屬性動(dòng)畫源碼分析篇

    今天小編就為大家分享一篇關(guān)于ObjectAnimator屬性動(dòng)畫源碼分析篇,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧
    2019-01-01
  • JetpackCompose Navigation導(dǎo)航實(shí)現(xiàn)流程

    JetpackCompose Navigation導(dǎo)航實(shí)現(xiàn)流程

    Navigation是Jetpack用于Android導(dǎo)航的組件,作用是處理頁(yè)面跳轉(zhuǎn),以及頁(yè)面跳轉(zhuǎn)過程中的交互。使用Navigation,你就需要為每個(gè)頁(yè)面設(shè)定一條唯一路徑,它是一個(gè)String常量,形式是DeepLink的樣子,從一個(gè)頁(yè)面跳轉(zhuǎn)到另一個(gè)頁(yè)面,它通過輸入目的地的路徑進(jìn)行轉(zhuǎn)跳
    2023-01-01
  • Android模擬器安裝APP出現(xiàn)INSTALL_FAILED_NO_MATCHING_ABIS錯(cuò)誤解決方案

    Android模擬器安裝APP出現(xiàn)INSTALL_FAILED_NO_MATCHING_ABIS錯(cuò)誤解決方案

    這篇文章主要介紹了 Android模擬器安裝APP出現(xiàn)INSTALL_FAILED_NO_MATCHING_ABIS錯(cuò)誤解決方案的相關(guān)資料,需要的朋友可以參考下
    2016-12-12
  • Android自定義進(jìn)度條效果

    Android自定義進(jìn)度條效果

    這篇文章主要為大家詳細(xì)介紹了Android自定義進(jìn)度條效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2018-08-08
  • android輸入框內(nèi)容改變的監(jiān)聽事件實(shí)例

    android輸入框內(nèi)容改變的監(jiān)聽事件實(shí)例

    下面小編就為大家分享一篇android輸入框內(nèi)容改變的監(jiān)聽事件實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2018-02-02
  • TabLayout+ViewPager實(shí)現(xiàn)切頁(yè)的示例代碼

    TabLayout+ViewPager實(shí)現(xiàn)切頁(yè)的示例代碼

    這篇文章主要介紹了TabLayout+ViewPager實(shí)現(xiàn)切頁(yè)的示例代碼,可實(shí)現(xiàn)左右滑動(dòng)切換視圖界面和點(diǎn)擊切換,非常具有實(shí)用價(jià)值,需要的朋友可以參考下
    2019-01-01
  • Android SdkVersion的區(qū)別及獲取版本信息方法

    Android SdkVersion的區(qū)別及獲取版本信息方法

    下面小編就為大家?guī)硪黄狝ndroid SdkVersion的區(qū)別及獲取版本信息方法。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2017-03-03

最新評(píng)論