浅析 - Android LiveData

前言

https://developer.android.com/reference/android/arch/lifecycle/LiveData?hl=zh-cn
https://developer.android.com/topic/libraries/architecture/livedata?hl=zh-cn

LiveData在整个架构体系中起到了桥梁作用,此外LiveData还持有了数据,并做相应的分发。

LiveData与外界也是个被观察者与观察者的关系。

在这里插入图片描述

在观察者模式的基础上,还为其加上了LifecycleObserver,让其感知生命周期变化可以自己解注册观察者,不可感知与可感知分别对应了observerForever()observer()两个方法。

LiveData相关的类不多,但是各个很有趣。

LiveData

上文说过,LiveData中有两种不同的注册观察者的方式,一种是带有生命周期感知的注册方式,另一种是直接注册(需要手动解注册)。

这其中分别对应了LiveData的中的内部类AlwaysActiveObserverLifecycleBoundObserver,这两个为直接继承自ObserverWrapper

ObserverWrapper内部也很简单,对LiveData是否处于激活状态做了处理与封装,当观察者数量mActiveCount首次大于0时且LiveData处于激活状态时,调用onActive();当观察者数量mActiveCount等于0且LiveData不处于激活状态时,调用onInactive()

LifecycleBoundObserver中集成了LifecycleObserver的子类GenericLifecycleObserver,用来对生命周期做出改变,shouldBeActive()方法则判断了当前LifecycleOwner的当前状态至少为STARTED才能变为激活态。

AlwaysActiveObserver则很简单,shouldBeActive()始终返回true

下面分别让看一下带有生命周期与不带有生命周期的使用LiveData的时序图:

observer(owner, observer)

在这里插入图片描述

observerForever(observer)

在这里插入图片描述

这两个路线的逻辑都很简单,这里就不赘述了,最后都在considerNotify()完成了任务分发:

private void considerNotify(ObserverWrapper observer) {
    if (!observer.mActive) {
        return;
    }
    ... 
    if (!observer.shouldBeActive()) {
        observer.activeStateChanged(false);
        return;
    }
   ... 
    observer.mObserver.onChanged((T) mData);
}

MediatorData

该类直接继承自LiveData,除了可以使用LiveData的基础能力外,还具有将多个LiveData组合在一起的能力。任意一个被组合的LiveData发生变化时,MediatorData的观察者都可以收到改变通知。

其中的关键在于Source这个类,它不仅组合持有LiveDataObserver,同时还继承自Observer,这就代表它具有在LiveData数据发生变化时,将通知再次分发的能力。

在这里插入图片描述

Transformations

与上面不同的是,LiveData提供了持有数据和分发的能力,MediatorLiveData则提供了将多个LiveData组合在一起的能力,Transformations虽然是个工具类,但是却提供了转换LiveData的能力。

LiveData类的转换工具类
可以使用工具类在观察者的生命周期中传递信息。除非观察者正在观察返回的LiveData对象,否则不会计算转换。
因为转换是懒惰地计算的,所以与生命周期相关的行为被隐式传递下去,而不需要额外的显式调用或依赖。

这种能力分为两种:

  • 对LiveData传递的数据进行处理转换的能力。例如:本来传递的是 “test”,经过转换可以将其加工成"test+test"。
  • 对LiveData传递的数据进行二次包装让其成为LiveData的能力。 例如:第一个LiveData的传递数据结果为用户名,但是实际上还想根据这个用户名查询用户的详细信息,就可以根据这个LiveData的结果再包装成第二个可以查询详细信息的LiveData。

首先看下其第一个能力:map - 映射
由于MediatorLiveData可以将多个LiveData进行组合,并观察其LiveData的数据变化,这就可以利用其Observer.onChanged()这个抓手,将结果结果数据进行一次处理,再将其分发给result

public static <X, Y> LiveData<Y> map(LiveData<X> source, final Function<X, Y> func) {
    final MediatorLiveData<Y> result = new MediatorLiveData<>();
    result.addSource(source, new Observer<X>() {
        public void onChanged(@Nullable X x) {
            // 对x数据进行处理(apply) 并对结果进行分发
            result.setValue(func.apply(x));
        }
    });
    return result;
}

再看下第二个能力:switchMap - 转换映射

虽然switchMap内部嵌套了多次,但是可以将其分离为两层:

  • 第一层result.addSource(trigger, ...,该操作理解为是为了获得懒计算的能力,由于LiveData特性决定,只有观察者注册时onChanged才会被调用,那么位于其中func.apply()才会执行计算。
  • 第二层result.addSource(mSource,...,该操作是为了获取经过func.apply得到的LiveData的计算结果,只有得到新的结果,才能再借助result的能力将其分发给观察者。
public static <X, Y> LiveData<Y> switchMap( LiveData<X> trigger, Function<X, LiveData<Y>> func) {
      final MediatorLiveData<Y> result = new MediatorLiveData<>();
      // 为func提供懒惰计算的能力
      result.addSource(trigger, new Observer<X>() {
          LiveData<Y> mSource;
          
          public void onChanged(@Nullable X x) {
              // 对x结果进行映射转换,得到一个新的LiveData
              LiveData<Y> newLiveData = func.apply(x);
              if (mSource == newLiveData) {
                  return;
              }
              if (mSource != null) {
                  result.removeSource(mSource);
              }
              mSource = newLiveData;
              if (mSource != null) {
                  // 将新的LiveData注册到result中
                  result.addSource(mSource, new Observer<Y>() {
                      public void onChanged(@Nullable Y y) {
                          result.setValue(y);
                      }
                  });
              }
          }
      });
      return result;
  }
releaseRuntimeClasspath - Resolved configuration for runtime for variant: release +--- androidx.appcompat:appcompat:1.6.1 | +--- androidx.activity:activity:1.6.0 -> 1.8.0 | | +--- androidx.annotation:annotation:1.1.0 -> 1.3.0 | | +--- androidx.collection:collection:1.0.0 -> 1.1.0 | | | \--- androidx.annotation:annotation:1.1.0 -> 1.3.0 | | +--- androidx.core:core:1.8.0 -> 1.9.0 | | | +--- androidx.annotation:annotation:1.2.0 -> 1.3.0 | | | +--- androidx.annotation:annotation-experimental:1.3.0 | | | | \--- org.jetbrains.kotlin:kotlin-stdlib:1.7.10 -> 1.8.22 | | | | +--- org.jetbrains.kotlin:kotlin-stdlib-common:1.8.22 | | | | \--- org.jetbrains:annotations:13.0 | | | +--- androidx.collection:collection:1.0.0 -> 1.1.0 (*) | | | +--- androidx.concurrent:concurrent-futures:1.0.0 -> 1.1.0 | | | | +--- androidx.annotation:annotation:1.1.0 -> 1.3.0 | | | | \--- com.google.guava:listenablefuture:1.0 | | | +--- androidx.lifecycle:lifecycle-runtime:2.3.1 -> 2.6.1 | | | | +--- androidx.annotation:annotation:1.1.0 -> 1.3.0 | | | | +--- androidx.arch.core:core-common:2.2.0 | | | | | \--- androidx.annotation:annotation:1.1.0 -> 1.3.0 | | | | +--- androidx.arch.core:core-runtime:2.2.0 | | | | | +--- androidx.annotation:annotation:1.1.0 -> 1.3.0 | | | | | \--- androidx.arch.core:core-common:2.2.0 (*) | | | | +--- androidx.lifecycle:lifecycle-common:2.6.1 | | | | | +--- androidx.annotation:annotation:1.1.0 -> 1.3.0 | | | | | +--- org.jetbrains.kotlin:kotlin-stdlib:1.8.10 -> 1.8.22 (*) | | | | | +--- org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4 | | | | | | +--- org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4 | | | | | | | \--- org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.6.4 | | | | | | | +--- org.jetbrains.kotlinx:kotlinx-coroutines-bom:1.6.4 | | | | | | | | +--- org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4 (c) | | | | | | | | +--- org.jetbrains.kotlinx:kotlinx-coroutines-core:1.6.4 (c) | | | | | | | | \--- org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:1.6.4 (c) | | | | | | | +--- org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.6.21 -> 1.8.22 | | | | | | | | +--- org.jetbrains.kotlin:kotlin-stdlib:1.8.22 (*) | | | | | | | | \--- org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.8.22 | | | | | | | | \--- org.jetbrains.kotlin:kotlin-stdlib:1.8.22 (*) | | | | | | | \--- org.jetbrains.kotlin:kotlin-stdlib-common:1.6.21 -> 1.8.22 | | | | | | +--- org.jetbrains.kotlinx:kotlinx-coroutines-bom:1.6.4 (*) | | | | | | \--- org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.6.21 -> 1.8.22 (*) | | | | | +--- androidx.lifecycle:lifecycle-livedata:2.6.1 (c) | | | | | +--- androidx.lifecycle:lifecycle-livedata-core:2.6.1 (c) | | | | | +--- androidx.lifecycle:lifecycle-process:2.6.1 (c) | | | | | +--- androidx.lifecycle:lifecycle-runtime:2.6.1 (c) | | | | | +--- androidx.lifecycle:lifecycle-viewmodel:2.6.1 (c) | | | | | \--- androidx.lifecycle:lifecycle-viewmodel-savedstate:2.6.1 (c) | | | | +--- androidx.profileinstaller:profileinstaller:1.3.0 | | | | | +--- androidx.annotation:annotation:1.2.0 -> 1.3.0 | | | | | +--- androidx.concurrent:concurrent-futures:1.1.0 (*) | | | | | +--- androidx.startup:startup-runtime:1.1.1 | | | | | | +--- androidx.annotation:annotation:1.1.0 -> 1.3.0 | | | | | | \--- androidx.tracing:tracing:1.0.0 | | | | | | \--- androidx.annotation:annotation:1.1.0 -> 1.3.0 | | | | | \--- com.google.guava:listenablefuture:1.0 | | | | +--- org.jetbrains.kotlin:kotlin-stdlib:1.8.10 -> 1.8.22 (*) | | | | +--- androidx.lifecycle:lifecycle-common:2.6.1 (c) | | | | +--- androidx.lifecycle:lifecycle-livedata-core:2.6.1 (c) | | | | +--- androidx.lifecycle:lifecycle-process:2.6.1 (c) | | | | +--- androidx.lifecycle:lifecycle-viewmodel:2.6.1 (c) | | | | +--- androidx.lifecycle:lifecycle-viewmodel-savedstate:2.6.1 (c) | | | | \--- androidx.lifecycle:lifecycle-livedata:2.6.1 (c) | | | +--- androidx.versionedparcelable:versionedparcelable:1.1.1 | | | | +--- androidx.annotation:annotation:1.1.0 -> 1.3.0 | | | | \--- androidx.collection:collection:1.0.0 -> 1.1.0 (*) | | | \--- androidx.core:core-ktx:1.9.0 (c) | | +--- androidx.lifecycle:lifecycle-runtime:2.6.1 (*) | | +--- androidx.lifecycle:lifecycle-viewmodel:2.6.1 | | | +--- androidx.annotation:annotation:1.1.0 -> 1.3.0 | | | +--- org.jetbrains.kotlin:kotlin-stdlib:1.8.10 -> 1.8.22 (*) | | | +--- androidx.lifecycle:lifecycle-common:2.6.1 (c) | | | +--- androidx.lifecycle:lifecycle-livedata-core:2.6.1 (c) | | | +--- androidx.lifecycle:lifecycle-process:2.6.1 (c) | | | +--- androidx.lifecycle:lifecycle-runtime:2.6.1 (c) | | | +--- androidx.lifecycle:lifecycle-viewmodel-savedstate:2.6.1 (c) | | | \--- androidx.lifecycle:lifecycle-livedata:2.6.1 (c) | | +--- androidx.lifecycle:lifecycle-viewmodel-savedstate:2.6.1 | | | +--- androidx.annotation:annotation:1.0.0 -> 1.3.0 | | | +--- androidx.core:core-ktx:1.2.0 -> 1.9.0 | | | | +--- androidx.annotation:annotation:1.1.0 -> 1.3.0 | | | | +--- androidx.core:core:1.9.0 (*) | | | | +--- org.jetbrains.kotlin:kotlin-stdlib:1.7.10 -> 1.8.22 (*) | | | | \--- androidx.core:core:1.9.0 (c) | | | +--- androidx.lifecycle:lifecycle-livedata-core:2.6.1 | | | | +--- androidx.arch.core:core-common:2.1.0 -> 2.2.0 (*) | | | | +--- androidx.arch.core:core-runtime:2.1.0 -> 2.2.0 (*) | | | | +--- androidx.lifecycle:lifecycle-common:2.6.1 (*) | | | | +--- org.jetbrains.kotlin:kotlin-stdlib:1.8.10 -> 1.8.22 (*) | | | | +--- androidx.lifecycle:lifecycle-common:2.6.1 (c) | | | | +--- androidx.lifecycle:lifecycle-livedata:2.6.1 (c) | | | | +--- androidx.lifecycle:lifecycle-process:2.6.1 (c) | | | | +--- androidx.lifecycle:lifecycle-runtime:2.6.1 (c) | | | | +--- androidx.lifecycle:lifecycle-viewmodel:2.6.1 (c) | | | | \--- androidx.lifecycle:lifecycle-viewmodel-savedstate:2.6.1 (c) | | | +--- androidx.lifecycle:lifecycle-viewmodel:2.6.1 (*) | | | +--- androidx.savedstate:savedstate:1.2.1 | | | | +--- androidx.annotation:annotation:1.1.0 -> 1.3.0 | | | | +--- androidx.arch.core:core-common:2.1.0 -> 2.2.0 (*) | | | | +--- androidx.lifecycle:lifecycle-common:2.6.1 (*) | | | | \--- org.jetbrains.kotlin:kotlin-stdlib:1.8.10 -> 1.8.22 (*) | | | +--- org.jetbrains.kotlin:kotlin-stdlib:1.8.10 -> 1.8.22 (*) | | | +--- org.jetbrains.kotlinx:kotlinx-coroutines-android:1.6.4 (*) | | | +--- androidx.lifecycle:lifecycle-common:2.6.1 (c) | | | +--- androidx.lifecycle:lifecycle-livedata-core:2.6.1 (c) | | | +--- androidx.lifecycle:lifecycle-process:2.6.1 (c) | | | +--- androidx.lifecycle:lifecycle-runtime:2.6.1 (c) | | | +--- androidx.lifecycle:lifecycle-viewmodel:2.6.1 (c) | | | \--- androidx.lifecycle:lifecycle-livedata:2.6.1 (c) | | +--- androidx.profileinstaller:profileinstaller:1.3.0 (*) | | +--- androidx.savedstate:savedstate:1.2.1 (*) | | +--- androidx.tracing:tracing:1.0.0 (*) | | \--- org.jetbrains.kotlin:kotlin-stdlib:1.8.22 (*) | +--- androidx.annotation:annotation:1.3.0 | +--- androidx.appcompat:appcompat-resources:1.6.1 | | +--- androidx.annotation:annotation:1.2.0 -> 1.3.0 | | +--- androidx.collection:collection:1.0.0 -> 1.1.0 (*) | | +--- androidx.core:core:1.6.0 -> 1.9.0 (*) | | +--- androidx.vectordrawable:vectordrawable:1.1.0 | | | +--- androidx.annotation:annotation:1.1.0 -> 1.3.0 | | | +--- androidx.core:core:1.1.0 -> 1.9.0 (*) | | | \--- androidx.collection:collection:1.1.0 (*) | | +--- androidx.vectordrawable:vectordrawable-animated:1.1.0 | | | +--- androidx.vectordrawable:vectordrawable:1.1.0 (*) | | | +--- androidx.interpolator:interpolator:1.0.0 | | | | \--- androidx.annotation:annotation:1.0.0 -> 1.3.0 | | | \--- androidx.collection:collection:1.1.0 (*) | | \--- androidx.appcompat:appcompat:1.6.1 (c) | +--- androidx.collection:collection:1.0.0 -> 1.1.0 (*) | +--- androidx.core:core:1.9.0 (*) | +--- androidx.core:core-ktx:1.8.0 -> 1.9.0 (*) | +--- androidx.cursoradapter:cursoradapter:1.0.0 | | \--- androidx.annotation:annotation:1.0.0 -> 1.3.0 | +--- androidx.drawerlayout:drawerlayout:1.0.0 -> 1.1.1 | | +--- androidx.annotation:annotation:1.1.0 -> 1.3.0 | | +--- androidx.core:core:1.2.0 -> 1.9.0 (*) | | \--- androidx.customview:customview:1.1.0 | | +--- androidx.annotation:annotation:1.1.0 -> 1.3.0 | | +--- androidx.core:core:1.3.0 -> 1.9.0 (*) | | \--- androidx.collection:collection:1.1.0 (*) | +--- androidx.emoji2:emoji2:1.2.0 | | +--- androidx.annotation:annotation:1.2.0 -> 1.3.0 | | +--- androidx.collection:collection:1.1.0 (*) | | +--- androidx.core:core:1.3.0 -> 1.9.0 (*) | | +--- androidx.lifecycle:lifecycle-process:2.4.1 -> 2.6.1 | | | +--- androidx.annotation:annotation:1.2.0 -> 1.3.0 | | | +--- androidx.lifecycle:lifecycle-runtime:2.6.1 (*) | | | +--- androidx.startup:startup-runtime:1.1.1 (*) | | | +--- org.jetbrains.kotlin:kotlin-stdlib:1.8.10 -> 1.8.22 (*) | | | +--- androidx.lifecycle:lifecycle-common:2.6.1 (c) | | | +--- androidx.lifecycle:lifecycle-livedata:2.6.1 (c) | | | +--- androidx.lifecycle:lifecycle-livedata-core:2.6.1 (c) | | | +--- androidx.lifecycle:lifecycle-runtime:2.6.1 (c) | | | +--- androidx.lifecycle:lifecycle-viewmodel:2.6.1 (c) | | | \--- androidx.lifecycle:lifecycle-viewmodel-savedstate:2.6.1 (c) | | \--- androidx.startup:startup-runtime:1.0.0 -> 1.1.1 (*) | +--- androidx.emoji2:emoji2-views-helper:1.2.0 | | +--- androidx.collection:collection:1.1.0 (*) | | +--- androidx.core:core:1.3.0 -> 1.9.0 (*) | | \--- androidx.emoji2:emoji2:1.2.0 (*) | +--- androidx.fragment:fragment:1.3.6 | | +--- androidx.annotation:annotation:1.1.0 -> 1.3.0 | | +--- androidx.core:core:1.2.0 -> 1.9.0 (*) | | +--- androidx.collection:collection:1.1.0 (*) | | +--- androidx.viewpager:viewpager:1.0.0 | | | +--- androidx.annotation:annotation:1.0.0 -> 1.3.0 | | | +--- androidx.core:core:1.0.0 -> 1.9.0 (*) | | | \--- androidx.customview:customview:1.0.0 -> 1.1.0 (*) | | +--- androidx.loader:loader:1.0.0 | | | +--- androidx.annotation:annotation:1.0.0 -> 1.3.0 | | | +--- androidx.core:core:1.0.0 -> 1.9.0 (*) | | | +--- androidx.lifecycle:lifecycle-livedata:2.0.0 -> 2.6.1 | | | | +--- androidx.arch.core:core-common:2.1.0 -> 2.2.0 (*) | | | | +--- androidx.arch.core:core-runtime:2.1.0 -> 2.2.0 (*) | | | | +--- androidx.lifecycle:lifecycle-livedata-core:2.6.1 (*) | | | | +--- org.jetbrains.kotlin:kotlin-stdlib:1.8.10 -> 1.8.22 (*) | | | | +--- androidx.lifecycle:lifecycle-common:2.6.1 (c) | | | | +--- androidx.lifecycle:lifecycle-livedata-core:2.6.1 (c) | | | | +--- androidx.lifecycle:lifecycle-process:2.6.1 (c) | | | | +--- androidx.lifecycle:lifecycle-runtime:2.6.1 (c) | | | | +--- androidx.lifecycle:lifecycle-viewmodel:2.6.1 (c) | | | | \--- androidx.lifecycle:lifecycle-viewmodel-savedstate:2.6.1 (c) | | | \--- androidx.lifecycle:lifecycle-viewmodel:2.0.0 -> 2.6.1 (*) | | +--- androidx.activity:activity:1.2.4 -> 1.8.0 (*) | | +--- androidx.lifecycle:lifecycle-livedata-core:2.3.1 -> 2.6.1 (*) | | +--- androidx.lifecycle:lifecycle-viewmodel:2.3.1 -> 2.6.1 (*) | | +--- androidx.lifecycle:lifecycle-viewmodel-savedstate:2.3.1 -> 2.6.1 (*) | | +--- androidx.savedstate:savedstate:1.1.0 -> 1.2.1 (*) | | \--- androidx.annotation:annotation-experimental:1.0.0 -> 1.3.0 (*) | +--- androidx.lifecycle:lifecycle-runtime:2.5.1 -> 2.6.1 (*) | +--- androidx.lifecycle:lifecycle-viewmodel:2.5.1 -> 2.6.1 (*) | +--- androidx.resourceinspection:resourceinspection-annotation:1.0.1 | | \--- androidx.annotation:annotation:1.1.0 -> 1.3.0 | +--- androidx.savedstate:savedstate:1.2.0 -> 1.2.1 (*) | +--- org.jetbrains.kotlin:kotlin-stdlib:1.7.10 -> 1.8.22 (*) | \--- androidx.appcompat:appcompat-resources:1.6.1 (c) +--- com.google.android.material:material:1.10.0 -> 1.11.0 | +--- org.jetbrains.kotlin:kotlin-bom:1.8.22 | | +--- org.jetbrains.kotlin:kotlin-stdlib:1.8.22 (c) | | +--- org.jetbrains.kotlin:kotlin-stdlib-common:1.8.22 (c) | | +--- org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.8.22 (c) | | \--- org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.8.22 (c) | +--- com.google.errorprone:error_prone_annotations:2.15.0 | +--- androidx.activity:activity:1.8.0 (*) | +--- androidx.annotation:annotation:1.2.0 -> 1.3.0 | +--- androidx.appcompat:appcompat:1.6.1 (*) | +--- androidx.cardview:cardview:1.0.0 | | \--- androidx.annotation:annotation:1.0.0 -> 1.3.0 | +--- androidx.coordinatorlayout:coordinatorlayout:1.1.0 | | +--- androidx.annotation:annotation:1.1.0 -> 1.3.0 | | +--- androidx.core:core:1.1.0 -> 1.9.0 (*) | | +--- androidx.customview:customview:1.0.0 -> 1.1.0 (*) | | \--- androidx.collection:collection:1.0.0 -> 1.1.0 (*) | +--- androidx.constraintlayout:constraintlayout:2.0.1 -> 2.1.4 | | +--- androidx.appcompat:appcompat:1.2.0 -> 1.6.1 (*) | | +--- androidx.core:core:1.3.2 -> 1.9.0 (*) | | \--- androidx.constraintlayout:constraintlayout-core:1.0.4 | +--- androidx.core:core:1.6.0 -> 1.9.0 (*) | +--- androidx.drawerlayout:drawerlayout:1.1.1 (*) | +--- androidx.dynamicanimation:dynamicanimation:1.0.0 | | +--- androidx.core:core:1.0.0 -> 1.9.0 (*) | | +--- androidx.collection:collection:1.0.0 -> 1.1.0 (*) | | \--- androidx.legacy:legacy-support-core-utils:1.0.0 | | +--- androidx.annotation:annotation:1.0.0 -> 1.3.0 | | +--- androidx.core:core:1.0.0 -> 1.9.0 (*) | | +--- androidx.documentfile:documentfile:1.0.0 | | | \--- androidx.annotation:annotation:1.0.0 -> 1.3.0 | | +--- androidx.loader:loader:1.0.0 (*) | | +--- androidx.localbroadcastmanager:localbroadcastmanager:1.0.0 | | | \--- androidx.annotation:annotation:1.0.0 -> 1.3.0 | | \--- androidx.print:print:1.0.0 | | \--- androidx.annotation:annotation:1.0.0 -> 1.3.0 | +--- androidx.annotation:annotation-experimental:1.0.0 -> 1.3.0 (*) | +--- androidx.fragment:fragment:1.2.5 -> 1.3.6 (*) | +--- androidx.lifecycle:lifecycle-runtime:2.0.0 -> 2.6.1 (*) | +--- androidx.recyclerview:recyclerview:1.0.0 -> 1.1.0 | | +--- androidx.annotation:annotation:1.1.0 -> 1.3.0 | | +--- androidx.core:core:1.1.0 -> 1.9.0 (*) | | +--- androidx.customview:customview:1.0.0 -> 1.1.0 (*) | | \--- androidx.collection:collection:1.0.0 -> 1.1.0 (*) | +--- androidx.resourceinspection:resourceinspection-annotation:1.0.1 (*) | +--- androidx.transition:transition:1.2.0 | | +--- androidx.annotation:annotation:1.1.0 -> 1.3.0 | | +--- androidx.core:core:1.0.1 -> 1.9.0 (*) | | \--- androidx.collection:collection:1.0.0 -> 1.1.0 (*) | +--- androidx.vectordrawable:vectordrawable:1.1.0 (*) | \--- androidx.viewpager2:viewpager2:1.0.0 | +--- androidx.annotation:annotation:1.1.0 -> 1.3.0 | +--- androidx.fragment:fragment:1.1.0 -> 1.3.6 (*) | +--- androidx.recyclerview:recyclerview:1.1.0 (*) | +--- androidx.core:core:1.1.0 -> 1.9.0 (*) | \--- androidx.collection:collection:1.1.0 (*) +--- com.google.android.material:material:1.11.0 (*) +--- androidx.activity:activity:1.8.0 (*) \--- androidx.constraintlayout:constraintlayout:2.1.4 (*) (c) - A dependency constraint, not a dependency. The dependency affected by the constraint occurs elsewhere in the tree. (*) - Indicates repeated occurrences of a transitive dependency subtree. Gradle expands transitive dependency subtrees only once per project; repeat occurrences only display the root of the subtree, followed by this annotation. A web-based, searchable dependency report is available by adding the --scan option. BUILD SUCCESSFUL in 20s 1 actionable task: 1 executed
最新发布
06-13
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值