中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Android基于MediatorLiveData如何實現紅點的統一管理

發布時間:2021-04-07 11:36:02 來源:億速云 閱讀:450 作者:小新 欄目:開發技術

這篇文章主要介紹了Android基于MediatorLiveData如何實現紅點的統一管理,具有一定借鑒價值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。

背景

小紅點在各個App內隨處可見,并且隨著需求的不斷迭代,需要展示小紅點的需求越來越多。

  • 不同需求之間,紅點顯示可能有沖突。

  • 不同頁面之間,紅點顯示會有關聯。

  • 同一個紅點,可能顯示成數字樣式,紅點樣式,文案樣式。

這個時候,如果沒有對紅點的展示邏輯做一個統一的抽象和管理的話,就會感覺很復雜,后續也不太好維護。

本文會基于MediatorLiveData,實現對紅點的統一管理。

需求分析

這里舉個例子,常見的紅點場景,類似qq首頁左上角紅點的顯示。

  1. 4個頁面,由首頁進入到隱私保護指引頁面,都有相應的紅點View顯示,去引導用戶進入到最里面的"隱私保護指引"頁面。

  2. 當用戶點擊紅點,進入到"隱私保護指引"頁面后,隱私保護指引對應的紅點就會消失,同時會觸發上級頁面的紅點刷新。

Android基于MediatorLiveData如何實現紅點的統一管理

Android基于MediatorLiveData如何實現紅點的統一管理

思路分析

樹形模型

一個App的頁面本身就是分級的,對于頁面的訪問路徑本質上就是個樹型結構。 整體的實現思路是用樹形模型去管理不同頁面的紅點。

  • 每個小紅點就是一個樹的節點,父節點的小紅點是否顯示,取決于它的子節點的并集結果。

  • 同一個頁面中的不同紅點。在樹中是同一個層級,屬于兄弟關系,互相獨立。

  • 子節點的狀態變化,會遞歸地去觸發父節點的狀態變化。

Android基于MediatorLiveData如何實現紅點的統一管理

具體代碼實現

那對應的代碼應該如何實現呢,難道真的要手動自己實現一棵樹?也不是不行,就是感覺有點小麻煩的樣子。 下面進入正題。

MediatorLiveData

官方提供了MediatorLiveData。

  • 通過addSource方法,可以監聽另一個LiveData的數據變化

  • 本身就是一個LiveData,可以被其他Observer觀察

這兩個特點,剛好滿足我們的需求實現。比如MediatorLiveData A觀察 MediatorLiveData B,MediatorLiveData B觀察 MediatorLiveData C 和MediatorLiveData D。并且被觀察的LiveData發生變化,作為觀察的LiveData都能收到通知。

通過管理多個LiveData之間的關系,這樣就可以間接實現了一棵樹的模型。

Android基于MediatorLiveData如何實現紅點的統一管理

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

  • 這里的實現,封裝成一個單例RedPointManager,暴露相應的紅點數據給外部。

  • LiveData數據驅動:RedPointManager內包含了多個LiveData,不同頁面的紅點View可以通過觀察對應的LiveData,來驅動自身的視圖變化。

  • 父節點使用MediatorLiveData,觀察相應的子節點LiveData。 葉子節點定義成普通的LiveData就行了,因為不需要觀察其他對象了。

Android基于MediatorLiveData如何實現紅點的統一管理

/**
 * 基于MediatorLiveData,實現樹形紅點管理
 */
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")
    /**
     * 構建樹型關系。按路徑層級,進行觀察。一般外部只需要改動最低層的紅點對應的LiveData,頂部的LiveData就會自動改變
     */
    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)
}

驗證刷新邏輯

一般情況下,只需要改動葉子節點的紅點對應的LiveData,父節點的LiveData就會自動改變。 基于上述代碼,調用testChangeDataC1方法后,監聽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)
  }
  
 //從輸出日志可以發現,底層的liveDataC1發生改變,觸發頂層的liveDataB1發生改變。liveDataB1的變化,也觸發了liveDataA發生改變。
RedPointManager init
testChangeDataC1: true
liveDataC1: true
lveDataB1: true
liveDataA: true

感謝你能夠認真閱讀完這篇文章,希望小編分享的“Android基于MediatorLiveData如何實現紅點的統一管理”這篇文章對大家有幫助,同時也希望大家多多支持億速云,關注億速云行業資訊頻道,更多相關知識等著你來學習!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

龙里县| 温州市| 和平区| 宿松县| 洛南县| 蒙自县| 惠安县| 博野县| 中方县| 河曲县| 岑溪市| 阿鲁科尔沁旗| 和政县| 巨野县| 卓资县| 茶陵县| 柏乡县| 保靖县| 昭觉县| 柯坪县| 澳门| 土默特右旗| 沐川县| 鹤山市| 丹巴县| 沙洋县| 桓台县| 建瓯市| 且末县| 炎陵县| 临江市| 乃东县| 柘城县| 房山区| 娄底市| 绩溪县| 静乐县| 茌平县| 谢通门县| 洪湖市| 三门县|