Adds StateFlow support to data binding

Bug: 162839058
Test: KotlinTestApp
Change-Id: I835d768cbc6d8bf44566bb15aae8fe786a005ed0
diff --git a/BUILD.bazel b/BUILD.bazel
index a6ad530..0b207b5 100644
--- a/BUILD.bazel
+++ b/BUILD.bazel
@@ -288,10 +288,11 @@
         "//prebuilts/tools/common/m2/repository/android/arch/lifecycle/extensions/1.0.0:aar",
         "//prebuilts/tools/common/m2/repository/android/arch/lifecycle/runtime/1.0.3:aar",
         "//prebuilts/tools/common/m2/repository/androidx/annotation/annotation/1.0.0:jar",
+        "//prebuilts/tools/common/m2/repository/androidx/annotation/annotation/1.1.0:jar",
         "//prebuilts/tools/common/m2/repository/androidx/appcompat/appcompat/1.0.0:aar",
         "//prebuilts/tools/common/m2/repository/androidx/appcompat/appcompat/1.0.2:aar",
-        "//prebuilts/tools/common/m2/repository/androidx/arch/core/core-common/2.0.0:jar",
-        "//prebuilts/tools/common/m2/repository/androidx/arch/core/core-runtime/2.0.0:aar",
+        "//prebuilts/tools/common/m2/repository/androidx/arch/core/core-common/2.1.0:jar",
+        "//prebuilts/tools/common/m2/repository/androidx/arch/core/core-runtime/2.1.0:aar",
         "//prebuilts/tools/common/m2/repository/androidx/asynclayoutinflater/asynclayoutinflater/1.0.0:aar",
         "//prebuilts/tools/common/m2/repository/androidx/cardview/cardview/1.0.0:aar",
         "//prebuilts/tools/common/m2/repository/androidx/collection/collection/1.0.0:jar",
@@ -306,14 +307,19 @@
         "//prebuilts/tools/common/m2/repository/androidx/interpolator/interpolator/1.0.0:aar",
         "//prebuilts/tools/common/m2/repository/androidx/legacy/legacy-support-core-ui/1.0.0:aar",
         "//prebuilts/tools/common/m2/repository/androidx/legacy/legacy-support-core-utils/1.0.0:aar",
-        "//prebuilts/tools/common/m2/repository/androidx/lifecycle/lifecycle-common/2.0.0:jar",
-        "//prebuilts/tools/common/m2/repository/androidx/lifecycle/lifecycle-extensions/2.0.0:aar",
-        "//prebuilts/tools/common/m2/repository/androidx/lifecycle/lifecycle-livedata-core/2.0.0:aar",
-        "//prebuilts/tools/common/m2/repository/androidx/lifecycle/lifecycle-livedata/2.0.0:aar",
-        "//prebuilts/tools/common/m2/repository/androidx/lifecycle/lifecycle-process/2.0.0:aar",
-        "//prebuilts/tools/common/m2/repository/androidx/lifecycle/lifecycle-runtime/2.0.0:aar",
-        "//prebuilts/tools/common/m2/repository/androidx/lifecycle/lifecycle-service/2.0.0:aar",
-        "//prebuilts/tools/common/m2/repository/androidx/lifecycle/lifecycle-viewmodel/2.0.0:aar",
+        "//prebuilts/tools/common/m2/repository/androidx/lifecycle/lifecycle-common/2.2.0:jar",
+        "//prebuilts/tools/common/m2/repository/androidx/lifecycle/lifecycle-extensions/2.2.0:aar",
+        "//prebuilts/tools/common/m2/repository/androidx/lifecycle/lifecycle-livedata-core-ktx/2.2.0:aar",
+        "//prebuilts/tools/common/m2/repository/androidx/lifecycle/lifecycle-livedata-core/2.2.0:aar",
+        "//prebuilts/tools/common/m2/repository/androidx/lifecycle/lifecycle-livedata-ktx/2.2.0:aar",
+        "//prebuilts/tools/common/m2/repository/androidx/lifecycle/lifecycle-livedata/2.0.0:aar",  #Workaround as loader:1.0.0 needs it
+        "//prebuilts/tools/common/m2/repository/androidx/lifecycle/lifecycle-livedata/2.2.0:aar",
+        "//prebuilts/tools/common/m2/repository/androidx/lifecycle/lifecycle-process/2.2.0:aar",
+        "//prebuilts/tools/common/m2/repository/androidx/lifecycle/lifecycle-runtime-ktx/2.2.0:aar",
+        "//prebuilts/tools/common/m2/repository/androidx/lifecycle/lifecycle-runtime/2.2.0:aar",
+        "//prebuilts/tools/common/m2/repository/androidx/lifecycle/lifecycle-service/2.2.0:aar",
+        "//prebuilts/tools/common/m2/repository/androidx/lifecycle/lifecycle-viewmodel-ktx/2.2.0:aar",
+        "//prebuilts/tools/common/m2/repository/androidx/lifecycle/lifecycle-viewmodel/2.2.0:aar",
         "//prebuilts/tools/common/m2/repository/androidx/loader/loader/1.0.0:aar",
         "//prebuilts/tools/common/m2/repository/androidx/localbroadcastmanager/localbroadcastmanager/1.0.0:aar",
         "//prebuilts/tools/common/m2/repository/androidx/print/print/1.0.0:aar",
@@ -335,9 +341,33 @@
         "//prebuilts/tools/common/m2/repository/com/android/support/support-media-compat/26.1.0:aar",
         "//prebuilts/tools/common/m2/repository/com/android/support/support-v4/26.1.0:aar",
         "//prebuilts/tools/common/m2/repository/com/android/support/support-vector-drawable/26.1.0:aar",
+        "//prebuilts/tools/common/m2/repository/com/github/gundy/semver4j/0.16.4:jar",
         "//prebuilts/tools/common/m2/repository/com/google/android/material/material/1.0.0:aar",
         "//prebuilts/tools/common/m2/repository/com/google/code/findbugs/jsr305/1.3.9:jar",
         "//prebuilts/tools/common/m2/repository/com/google/errorprone/error_prone_annotations/2.1.3:jar",
+        "//prebuilts/tools/common/m2/repository/de/undercouch/gradle-download-task/4.0.2:jar",
+        "//prebuilts/tools/common/m2/repository/org/antlr/antlr4-runtime/4.5.2-1:jar",
+        "//prebuilts/tools/common/m2/repository/org/jetbrains/intellij/deps/trove4j/1.0.20181211:jar",
+        "//prebuilts/tools/common/m2/repository/org/jetbrains/kotlin/kotlin-android-extensions/1.4.10:jar",
+        "//prebuilts/tools/common/m2/repository/org/jetbrains/kotlin/kotlin-annotation-processing-gradle/1.4.10:jar",
+        "//prebuilts/tools/common/m2/repository/org/jetbrains/kotlin/kotlin-build-common/1.4.10:jar",
+        "//prebuilts/tools/common/m2/repository/org/jetbrains/kotlin/kotlin-compiler-embeddable/1.4.10:jar",
+        "//prebuilts/tools/common/m2/repository/org/jetbrains/kotlin/kotlin-compiler-runner/1.4.10:jar",
+        "//prebuilts/tools/common/m2/repository/org/jetbrains/kotlin/kotlin-daemon-client/1.4.10:jar",
+        "//prebuilts/tools/common/m2/repository/org/jetbrains/kotlin/kotlin-daemon-embeddable/1.4.10:jar",
+        "//prebuilts/tools/common/m2/repository/org/jetbrains/kotlin/kotlin-gradle-plugin-api/1.4.10:jar",
+        "//prebuilts/tools/common/m2/repository/org/jetbrains/kotlin/kotlin-gradle-plugin-model/1.4.10:jar",
+        "//prebuilts/tools/common/m2/repository/org/jetbrains/kotlin/kotlin-gradle-plugin/1.4.10:jar",
+        "//prebuilts/tools/common/m2/repository/org/jetbrains/kotlin/kotlin-script-runtime/1.4.10:jar",
+        "//prebuilts/tools/common/m2/repository/org/jetbrains/kotlin/kotlin-scripting-common/1.4.10:jar",
+        "//prebuilts/tools/common/m2/repository/org/jetbrains/kotlin/kotlin-scripting-compiler-embeddable/1.4.10:jar",
+        "//prebuilts/tools/common/m2/repository/org/jetbrains/kotlin/kotlin-scripting-compiler-impl-embeddable/1.4.10:jar",
+        "//prebuilts/tools/common/m2/repository/org/jetbrains/kotlin/kotlin-scripting-jvm/1.4.10:jar",
+        "//prebuilts/tools/common/m2/repository/org/jetbrains/kotlin/kotlin-util-io/1.4.10:jar",
+        "//prebuilts/tools/common/m2/repository/org/jetbrains/kotlin/kotlin-util-klib/1.4.10:jar",
+        "//prebuilts/tools/common/m2/repository/org/jetbrains/kotlinx/kotlinx-coroutines-android/1.4.1:jar",
+        "//prebuilts/tools/common/m2/repository/org/jetbrains/kotlinx/kotlinx-coroutines-core/1.3.7:jar",
+        "//prebuilts/tools/common/m2/repository/org/jetbrains/kotlinx/kotlinx-coroutines-core/1.4.1:jar",
     ],
 )
 
@@ -350,6 +380,7 @@
         "//prebuilts/studio/sdk:platform-tools",
         "//prebuilts/studio/sdk:build-tools/latest",
         "//tools/buildSrc/base:version.properties",
+        "//tools/buildSrc/base:dependencies.properties",
         "//tools/data-binding:databinding.properties",
     ] + glob(
         ["extensions/**"],
diff --git a/compilationTests/build.gradle b/compilationTests/build.gradle
index 9398c5e..a42cc26 100644
--- a/compilationTests/build.gradle
+++ b/compilationTests/build.gradle
@@ -21,6 +21,7 @@
     testCompile 'com.android.tools:annotations:24.5.0'
     testCompile libs.guava
     testCompile libs.kotlin_stdlib
+    testCompile 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1'
 }
 
 afterEvaluate {
diff --git a/compilationTests/gradle/wrapper/gradle-wrapper.properties b/compilationTests/gradle/wrapper/gradle-wrapper.properties
index b6f6d38..73a14a3 100644
--- a/compilationTests/gradle/wrapper/gradle-wrapper.properties
+++ b/compilationTests/gradle/wrapper/gradle-wrapper.properties
@@ -4,4 +4,4 @@
 distributionPath=wrapper/dists
 zipStoreBase=GRADLE_USER_HOME
 zipStorePath=wrapper/dists
-distributionUrl=../../../../../../../external/gradle/gradle-4.1-bin.zip
+distributionUrl=../../../../../../../external/gradle/gradle-6.6-bin.zip
diff --git a/compilationTests/src/test/java/androidx/databinding/compilationTest/ObservableGetDetectionTest.kt b/compilationTests/src/test/java/androidx/databinding/compilationTest/ObservableGetDetectionTest.kt
index 1a0440d..001410b 100644
--- a/compilationTests/src/test/java/androidx/databinding/compilationTest/ObservableGetDetectionTest.kt
+++ b/compilationTests/src/test/java/androidx/databinding/compilationTest/ObservableGetDetectionTest.kt
@@ -26,7 +26,8 @@
 class ObservableGetDetectionTest(
         private val type: String,
         private val resolvedType: String, // e..g if it is ObservableInt, resolvedType is Int
-        private val getter: String
+        private val getter: String,
+        private val constructor: String
 ) : BaseCompilationTest() {
     @Test
     fun detectGetterCallsOnObservables() {
@@ -71,7 +72,7 @@
                     package com.example;
                     import androidx.databinding.*;
                     public class MyClass {
-                        public final $type value = new $type();
+                        public final $type value = $constructor;
                     }
                 """.trimIndent())
         writeFile("/app/src/main/res/layout/observable_get.xml",
@@ -100,7 +101,7 @@
                     package com.example;
                     import androidx.databinding.*;
                     public class MyClass {
-                        public final $type value = new $type();
+                        public final $type value = $constructor;
                         @InverseMethod("fromString")
                         public static String convertToString($resolvedType value) {
                             throw new RuntimeException("");
@@ -134,19 +135,31 @@
         @Parameterized.Parameters(name = "{0}")
         @JvmStatic
         fun params() = arrayOf(
-                arrayOf("ObservableByte", "byte"),
-                arrayOf("ObservableBoolean", "boolean"),
-                arrayOf("ObservableChar", "char"),
-                arrayOf("ObservableShort", "short"),
-                arrayOf("ObservableInt", "int"),
-                arrayOf("ObservableLong", "long"),
-                arrayOf("ObservableFloat", "float"),
-                arrayOf("ObservableDouble", "double"),
-                arrayOf("ObservableField<String>", "String")
+                arrayOf("androidx.databinding.ObservableByte", "byte"),
+                arrayOf("androidx.databinding.ObservableBoolean", "boolean"),
+                arrayOf("androidx.databinding.ObservableChar", "char"),
+                arrayOf("androidx.databinding.ObservableShort", "short"),
+                arrayOf("androidx.databinding.ObservableInt", "int"),
+                arrayOf("androidx.databinding.ObservableLong", "long"),
+                arrayOf("androidx.databinding.ObservableFloat", "float"),
+                arrayOf("androidx.databinding.ObservableDouble", "double"),
+                arrayOf("androidx.databinding.ObservableField<String>", "String")
         ).map {
-            arrayOf("androidx.databinding.${it[0]}", it[1], "get()")
+            arrayOf(it[0], it[1], "get()", "new ${it[0]}()")
         } + arrayOf(
-                arrayOf("androidx.lifecycle.MutableLiveData<String>", "String", "getValue()")
+                arrayOf(
+                        "androidx.lifecycle.MutableLiveData<String>",
+                        "String",
+                        "getValue()",
+                        "new androidx.lifecycle.MutableLiveData<String>()"
+                )
+        ) + arrayOf(
+                arrayOf(
+                        "kotlinx.coroutines.flow.MutableStateFlow<String>",
+                        "String",
+                        "getValue()",
+                        "kotlinx.coroutines.flow.StateFlowKt.MutableStateFlow(\"\")"
+                )
         )
     }
-}
\ No newline at end of file
+}
diff --git a/compilationTests/src/test/resources/app_build.gradle b/compilationTests/src/test/resources/app_build.gradle
index ab61387..ed269e3 100644
--- a/compilationTests/src/test/resources/app_build.gradle
+++ b/compilationTests/src/test/resources/app_build.gradle
@@ -1,4 +1,5 @@
 apply plugin: 'com.android.application'
+apply plugin: 'kotlin-android'
 
 android {
     compileSdkVersion rootProject.latestCompileSdk
@@ -26,6 +27,7 @@
 
 dependencies {
     compile fileTree(dir: 'libs', include: ['*.jar'])
-    implementation "androidx.lifecycle:lifecycle-livedata:2.0.0"
+    implementation "androidx.fragment:fragment:1.2.0"
+    implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1"
     !@{DEPENDENCIES}
 }
diff --git a/compilationTests/src/test/resources/commonBuildScript.gradle b/compilationTests/src/test/resources/commonBuildScript.gradle
index 35f21b4..cd94804 100644
--- a/compilationTests/src/test/resources/commonBuildScript.gradle
+++ b/compilationTests/src/test/resources/commonBuildScript.gradle
@@ -27,6 +27,7 @@
 
     dependencies {
         classpath "com.android.tools.build:gradle:${buildVersion}"
+        classpath libs.kotlin_gradle_plugin
     }
 }
 
diff --git a/compiler/src/main/java/android/databinding/tool/expr/Expr.java b/compiler/src/main/java/android/databinding/tool/expr/Expr.java
index 73770a5..c956dfc 100644
--- a/compiler/src/main/java/android/databinding/tool/expr/Expr.java
+++ b/compiler/src/main/java/android/databinding/tool/expr/Expr.java
@@ -191,14 +191,19 @@
         return getResolvedType().isObservable();
     }
 
-    public String getUpdateRegistrationCall() {
+    public String getUpdateRegistrationCall(int id, String value) {
         if (!isObservable()) {
             L.e("The expression isn't observable!");
         }
+        String lastParams = id + ", " + value + ");";
         if (getResolvedType().isLiveData()) {
-            return "updateLiveDataRegistration";
+            return "updateLiveDataRegistration(" + lastParams;
         }
-        return "updateRegistration";
+        if (getResolvedType().isStateFlow()) {
+            return "androidx.databinding.ViewDataBindingKtx."
+                    + "updateStateFlowRegistration(this, " + lastParams;
+        }
+        return "updateRegistration(" + lastParams;
     }
 
     public void setUnwrapObservableFields(boolean unwrapObservableFields) {
diff --git a/compiler/src/main/java/android/databinding/tool/reflection/ModelAnalyzer.kt b/compiler/src/main/java/android/databinding/tool/reflection/ModelAnalyzer.kt
index d2a86ee..37f0e8a 100644
--- a/compiler/src/main/java/android/databinding/tool/reflection/ModelAnalyzer.kt
+++ b/compiler/src/main/java/android/databinding/tool/reflection/ModelAnalyzer.kt
@@ -53,6 +53,12 @@
     val mutableLiveDataType  by lazy(LazyThreadSafetyMode.NONE) {
         loadClassErasure(libTypes.mutableLiveData)
     }
+    val stateFlowType  by lazy(LazyThreadSafetyMode.NONE) {
+        loadClassErasure(libTypes.stateFlow)
+    }
+    val mutableStateFlowDataType  by lazy(LazyThreadSafetyMode.NONE) {
+        loadClassErasure(libTypes.mutableStateFlow)
+    }
     val viewDataBindingType  by lazy(LazyThreadSafetyMode.NONE) {
         val klass = findClass(libTypes.viewDataBinding, null)
         Preconditions.checkNotNull(klass, "Cannot find %s class." +
@@ -141,6 +147,19 @@
         }
     }
 
+    private val dataBindingKtxClass by lazy {
+        findClass(libTypes.dataBindingKtx, null)
+    }
+
+    fun checkDataBindingKtx() {
+        Preconditions.checkNotNull(
+                dataBindingKtxClass, """Data binding ktx is not enabled.
+                |
+                |Add dataBinding.addKtx = true to your build.gradle to enable it."""
+                .trimMargin()
+        )
+    }
+
     fun findClass(className: String, imports: ImportBag?): ModelClass? {
         return classFinderCache.find(className, imports)
     }
diff --git a/compiler/src/main/java/android/databinding/tool/reflection/ModelClass.kt b/compiler/src/main/java/android/databinding/tool/reflection/ModelClass.kt
index 99b7f8c..fb60044 100644
--- a/compiler/src/main/java/android/databinding/tool/reflection/ModelClass.kt
+++ b/compiler/src/main/java/android/databinding/tool/reflection/ModelClass.kt
@@ -176,7 +176,8 @@
             return modelAnalyzer.observableType.isAssignableFrom(this) ||
                     modelAnalyzer.observableListType.isAssignableFrom(this) ||
                     modelAnalyzer.observableMapType.isAssignableFrom(this) ||
-                    (modelAnalyzer.liveDataType?.isAssignableFrom(this) ?: false)
+                    (modelAnalyzer.liveDataType?.isAssignableFrom(this) ?: false) ||
+                    (modelAnalyzer.stateFlowType?.isAssignableFrom(this) ?: false)
         }
 
     /**
@@ -206,24 +207,43 @@
     }
 
     /**
+     * @return whether or not this is a StateFlow
+     */
+    val isStateFlow by lazy(LazyThreadSafetyMode.NONE) {
+        val modelAnalyzer = ModelAnalyzer.getInstance()
+        val isStateFlow = modelAnalyzer.stateFlowType?.isAssignableFrom(erasure()) ?: false
+        if (isStateFlow) {
+            modelAnalyzer.checkDataBindingKtx()
+        }
+        isStateFlow
+    }
+
+    /**
+     * @return whether or not this is a MutableStateFlow
+     */
+    val isMutableStateFlow by lazy(LazyThreadSafetyMode.NONE) {
+        ModelAnalyzer.getInstance().mutableStateFlowDataType?.isAssignableFrom(erasure()) ?: false
+    }
+
+    /**
      * @return the name of the simple getter method when this is an ObservableField or LiveData or
-     * `null` for any other type
+     * Flow or `null` for any other type
      */
     val observableGetterName: String?
         get() = when {
             isObservableField -> "get"
-            isLiveData -> "getValue"
+            isLiveData || isStateFlow -> "getValue"
             else -> null
         }
 
     /**
      * @return the name of the simple setter method when this is an ObservableField or
-     * MutableLiveData or `null` for any other type.
+     * MutableLiveData or MutableStateFlow or `null` for any other type.
      */
     val observableSetterName: String?
         get() = when {
             isObservableField -> "set"
-            isMutableLiveData -> "setValue"
+            isMutableLiveData || isMutableStateFlow -> "setValue"
             else -> null
         }
 
@@ -651,4 +671,4 @@
             return fieldName
         }
     }
-}
\ No newline at end of file
+}
diff --git a/compiler/src/main/kotlin/android/databinding/tool/writer/LayoutBinderWriter.kt b/compiler/src/main/kotlin/android/databinding/tool/writer/LayoutBinderWriter.kt
index 26b8203..1130f32 100644
--- a/compiler/src/main/kotlin/android/databinding/tool/writer/LayoutBinderWriter.kt
+++ b/compiler/src/main/kotlin/android/databinding/tool/writer/LayoutBinderWriter.kt
@@ -754,7 +754,7 @@
                 block("public void ${it.setterName}(${if (it.resolvedType.isPrimitive) "" else "@Nullable "}$argType ${it.readableName})") {
                     val used = it.isIsUsedInCallback || it.isUsed
                     if (used && it.isObservable) {
-                        nl("${it.updateRegistrationCall}(${it.id}, ${it.readableName});");
+                        nl(it.getUpdateRegistrationCall(it.id, it.readableName))
                     }
                     nl("this.${it.fieldName} = ${it.readableName};")
                     if (used) {
@@ -1098,7 +1098,7 @@
                             app("", assignment)
                         }
                         it.value.filter { it.isObservable }.forEach { expr: Expr ->
-                            tab("${expr.updateRegistrationCall}(${expr.id}, ${expr.executePendingLocalName});")
+                            tab(expr.getUpdateRegistrationCall(expr.id, expr.executePendingLocalName))
                         }
                     }
 
diff --git a/compilerCommon/src/main/kotlin/android/databinding/tool/LibTypes.kt b/compilerCommon/src/main/kotlin/android/databinding/tool/LibTypes.kt
index 3b848a2..4a4a472 100644
--- a/compilerCommon/src/main/kotlin/android/databinding/tool/LibTypes.kt
+++ b/compilerCommon/src/main/kotlin/android/databinding/tool/LibTypes.kt
@@ -60,10 +60,22 @@
         convert("android.arch.lifecycle.MutableLiveData")
     }
 
+    val stateFlow by lazy(LazyThreadSafetyMode.NONE) {
+        "kotlinx.coroutines.flow.StateFlow"
+    }
+
+    val mutableStateFlow by lazy(LazyThreadSafetyMode.NONE) {
+        "kotlinx.coroutines.flow.MutableStateFlow"
+    }
+
     val dataBindingComponent by lazy(LazyThreadSafetyMode.NONE) {
         convert("android.databinding.DataBindingComponent")
     }
 
+    val dataBindingKtx by lazy(LazyThreadSafetyMode.NONE) {
+        "androidx.databinding.ViewDataBindingKtx"
+    }
+
     val dataBinderMapper by lazy(LazyThreadSafetyMode.NONE) {
         convert("android.databinding.DataBinderMapper")
     }
@@ -210,4 +222,4 @@
                 "android.arch.persistence." to "androidx.sqlite."
         )
     }
-}
\ No newline at end of file
+}
diff --git a/compilerCommon/src/test/kotlin/android/databinding/tool/store/AndroidXConversionTest.kt b/compilerCommon/src/test/kotlin/android/databinding/tool/store/AndroidXConversionTest.kt
index 07a757d..68fdd9b 100644
--- a/compilerCommon/src/test/kotlin/android/databinding/tool/store/AndroidXConversionTest.kt
+++ b/compilerCommon/src/test/kotlin/android/databinding/tool/store/AndroidXConversionTest.kt
@@ -54,4 +54,4 @@
                 `is`("androidx.recyclerview.widget.RecyclerView")
         )
     }
-}
\ No newline at end of file
+}
diff --git a/extensions-support/gradle/wrapper/gradle-wrapper.properties b/extensions-support/gradle/wrapper/gradle-wrapper.properties
index 273873f..fa1cc2e 100644
--- a/extensions-support/gradle/wrapper/gradle-wrapper.properties
+++ b/extensions-support/gradle/wrapper/gradle-wrapper.properties
@@ -1,5 +1,5 @@
 distributionBase=GRADLE_USER_HOME
 distributionPath=wrapper/dists
-distributionUrl=../../../../external/gradle/gradle-6.5-bin.zip
+distributionUrl=../../../../external/gradle/gradle-6.7.1-bin.zip
 zipStoreBase=GRADLE_USER_HOME
 zipStorePath=wrapper/dists
diff --git a/extensions/baseAdapters/build.gradle b/extensions/baseAdapters/build.gradle
index 85ab1db..603925b 100644
--- a/extensions/baseAdapters/build.gradle
+++ b/extensions/baseAdapters/build.gradle
@@ -96,4 +96,4 @@
     rename { String fileName ->
         "databinding-adapters.aar"
     }
-}
\ No newline at end of file
+}
diff --git a/extensions/build.gradle b/extensions/build.gradle
index 8b77e81..1bfd88b 100644
--- a/extensions/build.gradle
+++ b/extensions/build.gradle
@@ -51,6 +51,8 @@
     databindingProperties.load(new FileInputStream("$projectDir/../databinding.properties"))
     Properties buildToolsProperties = new Properties()
     buildToolsProperties.load(new FileInputStream("$projectDir/../../buildSrc/base/version.properties"))
+    Properties dependencyProperties = new Properties()
+    dependencyProperties.load(new FileInputStream("$projectDir/../../buildSrc/base/dependencies.properties"))
 
     def runningInIde = project.hasProperty('android.injected.invoked.from.ide')
     // this is done by bazel but if we are in IDE it also configures so we need to distinguish
@@ -107,7 +109,7 @@
     }
     ext.dataBindingConfig = databindingProperties
     def supportLibVersion = "1.0.0"
-    def lifecycleVersion = "2.0.0"
+    def lifecycleVersion = "2.2.0"
     ext.libs = [:]
     ext.libs.android_support_annotations = "androidx.annotation:annotation:$supportLibVersion"
     ext.libs.android_support_collection = "androidx.collection:collection:$supportLibVersion"
@@ -115,9 +117,14 @@
     ext.libs.android_support_appcompat_v7 = "androidx.appcompat:appcompat:$supportLibVersion"
     ext.libs.android_arch_lifecycle_extensions = "androidx.lifecycle:lifecycle-extensions:$lifecycleVersion"
     ext.libs.android_arch_lifecycle_runtime = "androidx.lifecycle:lifecycle-runtime:$lifecycleVersion"
+    ext.libs.android_arch_lifecycle_runtime_ktx = "androidx.lifecycle:lifecycle-runtime-ktx:$lifecycleVersion"
+    ext.libs.kotlin_gradle_plugin = dependencyProperties.kotlin_gradle_plugin
+    ext.libs.kotlin_stdlib = dependencyProperties.kotlin_stdlib
+    ext.libs.coroutines = "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1"
 
     dependencies {
         classpath "com.android.tools.build:gradle:$TOOLS_VERSION"
+        classpath rootProject.ext.libs.kotlin_gradle_plugin
     }
 
     if (!autoConfigured) {
@@ -177,8 +184,8 @@
             failOnVersionConflict()
 
             preferProjectModules()
-            force 'androidx.lifecycle:lifecycle-viewmodel:2.0.0'
-            force 'androidx.lifecycle:lifecycle-livedata-core:2.0.0'
+            force 'androidx.lifecycle:lifecycle-viewmodel:2.2.0'
+            force 'androidx.lifecycle:lifecycle-livedata-core:2.2.0'
             force 'androidx.fragment:fragment:1.0.0'
         }
     }
diff --git a/extensions/databindingKtx/build.gradle b/extensions/databindingKtx/build.gradle
new file mode 100644
index 0000000..4b8ae3e
--- /dev/null
+++ b/extensions/databindingKtx/build.gradle
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+apply plugin: 'com.android.library'
+apply plugin: 'kotlin-android'
+
+android {
+    compileSdkVersion dataBindingConfig.compileSdkVersion
+    buildToolsVersion dataBindingConfig.buildToolsVersion
+
+    defaultConfig {
+        minSdkVersion 14
+        targetSdkVersion dataBindingConfig.targetSdkVersion
+    }
+    compileOptions {
+        sourceCompatibility dataBindingConfig.javaTargetCompatibility
+        targetCompatibility dataBindingConfig.javaSourceCompatibility
+    }
+    buildTypes {
+        release {
+            minifyEnabled false
+        }
+    }
+    packagingOptions {
+        exclude 'META-INF/LICENSE.txt'
+        exclude 'META-INF/NOTICE.txt'
+    }
+}
+
+configurations {
+    jarArchives
+}
+
+dependencies {
+    implementation project(':library')
+    implementation rootProject.ext.libs.kotlin_stdlib
+    implementation rootProject.ext.libs.coroutines
+    api rootProject.ext.libs.android_arch_lifecycle_extensions
+    api rootProject.ext.libs.android_arch_lifecycle_runtime_ktx
+}
+
+//create jar tasks
+android.libraryVariants.all { variant ->
+    def name = variant.buildType.name
+
+    if (name.equals(com.android.builder.core.BuilderConstants.DEBUG)) {
+        return // Skip debug builds.
+    }
+    def suffix = name.capitalize()
+
+    def sourcesJarTask = project.tasks.create(name: "sourceJar${suffix}", type: Jar) {
+        classifier = 'sources'
+        from android.sourceSets.main.java.srcDirs
+    }
+
+    artifacts.add('archives', sourcesJarTask);
+}
+uploadArchives {
+    repositories {
+        mavenDeployer {
+            pom.artifactId = 'databinding-ktx'
+            pom.project {
+                licenses {
+                    license {
+                        name dataBindingConfig.licenseName
+                        url dataBindingConfig.licenseUrl
+                        distribution dataBindingConfig.licenseDistribution
+                    }
+                }
+            }
+        }
+    }
+}
+
+task prebuildAar(type : Copy) {
+    dependsOn uploadArchives
+    from "$buildDir/outputs/aar/databinding-ktx-release.aar"
+    into dataBindingConfig.prebuildFolder
+    rename { String fileName ->
+        "databinding-ktx.aar"
+    }
+}
diff --git a/extensions/databindingKtx/src/main/AndroidManifest.xml b/extensions/databindingKtx/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..60e62e5
--- /dev/null
+++ b/extensions/databindingKtx/src/main/AndroidManifest.xml
@@ -0,0 +1,17 @@
+<!--
+  Copyright (C) 2020 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+
+<manifest package="androidx.databinding.ktx" />
diff --git a/extensions/databindingKtx/src/main/java/androidx/databinding/ViewDataBindingKtx.kt b/extensions/databindingKtx/src/main/java/androidx/databinding/ViewDataBindingKtx.kt
new file mode 100644
index 0000000..509b44a
--- /dev/null
+++ b/extensions/databindingKtx/src/main/java/androidx/databinding/ViewDataBindingKtx.kt
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.databinding;
+
+import androidx.annotation.RestrictTo
+import androidx.lifecycle.LifecycleOwner
+import androidx.lifecycle.lifecycleScope
+import kotlinx.coroutines.Job
+import kotlinx.coroutines.flow.Flow
+import kotlinx.coroutines.flow.collect
+import java.lang.ref.ReferenceQueue
+
+/**
+ * Helper methods for data binding Ktx features.
+ */
+@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+object ViewDataBindingKtx {
+
+    /**
+     * Method object extracted out to attach a listener to a bound StateFlow object.
+     */
+    private val CREATE_STATE_FLOW_LISTENER =
+            CreateWeakListener { viewDataBinding, localFieldId, referenceQueue ->
+                StateFlowListener(viewDataBinding, localFieldId, referenceQueue)
+                        .listener
+            }
+
+    @Suppress("unused") // called by generated code
+    @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+    @JvmStatic
+    fun updateStateFlowRegistration(
+            viewDataBinding: ViewDataBinding,
+            localFieldId: Int,
+            observable: Flow<*>?
+    ): Boolean {
+        viewDataBinding.mInStateFlowRegisterObserver = true
+        try {
+            return viewDataBinding.updateRegistration(
+                    localFieldId, observable, CREATE_STATE_FLOW_LISTENER
+            )
+        } finally {
+            viewDataBinding.mInStateFlowRegisterObserver = false
+        }
+    }
+
+    internal class StateFlowListener(
+            binder: ViewDataBinding?,
+            localFieldId: Int,
+            referenceQueue: ReferenceQueue<ViewDataBinding>
+    ) : ObservableReference<Flow<Any?>> {
+
+        private var _lifecycleOwner : LifecycleOwner? = null
+        private var observerJob : Job? = null
+        private val listener = WeakListener<Flow<Any?>>(
+                binder, localFieldId, this, referenceQueue
+        )
+        override fun getListener(): WeakListener<Flow<Any?>> {
+            return listener
+        }
+
+        override fun addListener(target: Flow<Any?>?) {
+            val owner = _lifecycleOwner ?: return
+            if (target != null) {
+                startCollection(owner, target)
+            }
+        }
+
+        override fun removeListener(target: Flow<Any?>?) {
+            observerJob?.cancel()
+            observerJob = null
+        }
+
+        private fun startCollection(owner: LifecycleOwner, flow: Flow<Any?>) {
+            observerJob?.cancel()
+            observerJob = owner.lifecycleScope.launchWhenCreated {
+                flow.collect {
+                    listener.binder?.handleFieldChange(listener.mLocalFieldId, listener.target, 0)
+                }
+            }
+        }
+
+        override fun setLifecycleOwner(lifecycleOwner: LifecycleOwner?) {
+            if (_lifecycleOwner === lifecycleOwner) {
+                return
+            }
+            observerJob?.cancel()
+            _lifecycleOwner = lifecycleOwner
+            val target = listener.target
+            if (lifecycleOwner != null && target != null) {
+                startCollection(lifecycleOwner, target)
+            }
+        }
+    }
+}
diff --git a/extensions/library/build.gradle b/extensions/library/build.gradle
index 3963d83..774c49d 100644
--- a/extensions/library/build.gradle
+++ b/extensions/library/build.gradle
@@ -68,10 +68,10 @@
 
 dependencies {
     implementation rootProject.ext.libs.android_support_collection
-    implementation "androidx.databinding:databinding-common:${dataBindingConfig.version}"
+    api "androidx.databinding:databinding-common:${dataBindingConfig.version}"
     api project(':viewbinding')
-    compileOnly rootProject.ext.libs.android_arch_lifecycle_extensions
     api rootProject.ext.libs.android_arch_lifecycle_runtime
+    compileOnly rootProject.ext.libs.android_arch_lifecycle_extensions
 }
 
 //create jar tasks
diff --git a/extensions/library/src/main/java/androidx/databinding/CreateWeakListener.java b/extensions/library/src/main/java/androidx/databinding/CreateWeakListener.java
new file mode 100644
index 0000000..398e468
--- /dev/null
+++ b/extensions/library/src/main/java/androidx/databinding/CreateWeakListener.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.databinding;
+
+import androidx.annotation.RestrictTo;
+import java.lang.ref.ReferenceQueue;
+
+@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+interface CreateWeakListener {
+    WeakListener create(
+            ViewDataBinding viewDataBinding,
+            int localFieldId,
+            ReferenceQueue<ViewDataBinding> referenceQueue);
+}
diff --git a/extensions/library/src/main/java/androidx/databinding/ObservableReference.java b/extensions/library/src/main/java/androidx/databinding/ObservableReference.java
new file mode 100644
index 0000000..447d47e
--- /dev/null
+++ b/extensions/library/src/main/java/androidx/databinding/ObservableReference.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.databinding;
+
+import androidx.annotation.RestrictTo;
+import androidx.lifecycle.LifecycleOwner;
+
+@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+interface ObservableReference<T> {
+    WeakListener<T> getListener();
+    void addListener(T target);
+    void removeListener(T target);
+    void setLifecycleOwner(LifecycleOwner lifecycleOwner);
+}
diff --git a/extensions/library/src/main/java/androidx/databinding/ViewDataBinding.java b/extensions/library/src/main/java/androidx/databinding/ViewDataBinding.java
index 5df3a3c..9612bd6 100644
--- a/extensions/library/src/main/java/androidx/databinding/ViewDataBinding.java
+++ b/extensions/library/src/main/java/androidx/databinding/ViewDataBinding.java
@@ -92,8 +92,13 @@
      */
     private static final CreateWeakListener CREATE_PROPERTY_LISTENER = new CreateWeakListener() {
         @Override
-        public WeakListener create(ViewDataBinding viewDataBinding, int localFieldId) {
-            return new WeakPropertyListener(viewDataBinding, localFieldId).getListener();
+        public WeakListener create(
+                ViewDataBinding viewDataBinding,
+                int localFieldId,
+                ReferenceQueue<ViewDataBinding> referenceQueue
+        ) {
+            return new WeakPropertyListener(viewDataBinding, localFieldId, referenceQueue)
+                    .getListener();
         }
     };
 
@@ -102,8 +107,13 @@
      */
     private static final CreateWeakListener CREATE_LIST_LISTENER = new CreateWeakListener() {
         @Override
-        public WeakListener create(ViewDataBinding viewDataBinding, int localFieldId) {
-            return new WeakListListener(viewDataBinding, localFieldId).getListener();
+        public WeakListener create(
+                ViewDataBinding viewDataBinding,
+                int localFieldId,
+                ReferenceQueue<ViewDataBinding> referenceQueue
+        ) {
+            return new WeakListListener(viewDataBinding, localFieldId, referenceQueue)
+                    .getListener();
         }
     };
 
@@ -112,8 +122,13 @@
      */
     private static final CreateWeakListener CREATE_MAP_LISTENER = new CreateWeakListener() {
         @Override
-        public WeakListener create(ViewDataBinding viewDataBinding, int localFieldId) {
-            return new WeakMapListener(viewDataBinding, localFieldId).getListener();
+        public WeakListener create(
+                ViewDataBinding viewDataBinding,
+                int localFieldId,
+                ReferenceQueue<ViewDataBinding> referenceQueue
+        ) {
+            return new WeakMapListener(viewDataBinding, localFieldId, referenceQueue)
+                    .getListener();
         }
     };
 
@@ -122,8 +137,13 @@
      */
     private static final CreateWeakListener CREATE_LIVE_DATA_LISTENER = new CreateWeakListener() {
         @Override
-        public WeakListener create(ViewDataBinding viewDataBinding, int localFieldId) {
-            return new LiveDataListener(viewDataBinding, localFieldId).getListener();
+        public WeakListener create(
+                ViewDataBinding viewDataBinding,
+                int localFieldId,
+                ReferenceQueue<ViewDataBinding> referenceQueue
+        ) {
+            return new LiveDataListener(viewDataBinding, localFieldId, referenceQueue)
+                    .getListener();
         }
     };
 
@@ -272,6 +292,14 @@
     private boolean mInLiveDataRegisterObserver;
 
     /**
+     * When StateFlow first collects for chances, it notifies immediately that there was a
+     * change. This flag identifies that we've just started observing StateFlow and we should ignore
+     * the change notification.
+     */
+    @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+    protected boolean mInStateFlowRegisterObserver;
+
+    /**
      * Needed for backwards binary compatibility.
      * b/122936785
      * @hide
@@ -539,9 +567,10 @@
         return mRoot;
     }
 
-    private void handleFieldChange(int mLocalFieldId, Object object, int fieldId) {
-        if (mInLiveDataRegisterObserver) {
-            // We're in LiveData registration, which always results in a field change
+    @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+    protected void handleFieldChange(int mLocalFieldId, Object object, int fieldId) {
+        if (mInLiveDataRegisterObserver || mInStateFlowRegisterObserver) {
+            // We're in LiveData or StateFlow registration, which always results in a field change
             // that we can ignore. The value will be read immediately after anyway, so
             // there is no need to be dirty.
             return;
@@ -602,7 +631,8 @@
         return listener.getTarget();
     }
 
-    private boolean updateRegistration(int localFieldId, Object observable,
+    @RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+    protected boolean updateRegistration(int localFieldId, Object observable,
             CreateWeakListener listenerCreator) {
         if (observable == null) {
             return unregisterFrom(localFieldId);
@@ -679,7 +709,7 @@
         }
         WeakListener listener = mLocalFieldObservers[localFieldId];
         if (listener == null) {
-            listener = listenerCreator.create(this, localFieldId);
+            listener = listenerCreator.create(this, localFieldId, sReferenceQueue);
             mLocalFieldObservers[localFieldId] = listener;
             if (mLifecycleOwner != null) {
                 listener.setLifecycleOwner(mLifecycleOwner);
@@ -1374,66 +1404,16 @@
         );
     }
 
-    private interface ObservableReference<T> {
-        WeakListener<T> getListener();
-        void addListener(T target);
-        void removeListener(T target);
-        void setLifecycleOwner(LifecycleOwner lifecycleOwner);
-    }
-
-    private static class WeakListener<T> extends WeakReference<ViewDataBinding> {
-        private final ObservableReference<T> mObservable;
-        protected final int mLocalFieldId;
-        private T mTarget;
-
-        public WeakListener(ViewDataBinding binder, int localFieldId,
-                ObservableReference<T> observable) {
-            super(binder, sReferenceQueue);
-            mLocalFieldId = localFieldId;
-            mObservable = observable;
-        }
-
-        public void setLifecycleOwner(LifecycleOwner lifecycleOwner) {
-            mObservable.setLifecycleOwner(lifecycleOwner);
-        }
-
-        public void setTarget(T object) {
-            unregister();
-            mTarget = object;
-            if (mTarget != null) {
-                mObservable.addListener(mTarget);
-            }
-        }
-
-        public boolean unregister() {
-            boolean unregistered = false;
-            if (mTarget != null) {
-                mObservable.removeListener(mTarget);
-                unregistered = true;
-            }
-            mTarget = null;
-            return unregistered;
-        }
-
-        public T getTarget() {
-            return mTarget;
-        }
-
-        protected ViewDataBinding getBinder() {
-            ViewDataBinding binder = get();
-            if (binder == null) {
-                unregister(); // The binder is dead
-            }
-            return binder;
-        }
-    }
-
     private static class WeakPropertyListener extends Observable.OnPropertyChangedCallback
             implements ObservableReference<Observable> {
         final WeakListener<Observable> mListener;
 
-        public WeakPropertyListener(ViewDataBinding binder, int localFieldId) {
-            mListener = new WeakListener<Observable>(binder, localFieldId, this);
+        public WeakPropertyListener(
+                ViewDataBinding binder,
+                int localFieldId,
+                ReferenceQueue<ViewDataBinding> referenceQueue
+        ) {
+            mListener = new WeakListener<Observable>(binder, localFieldId, this, referenceQueue);
         }
 
         @Override
@@ -1473,8 +1453,14 @@
             implements ObservableReference<ObservableList> {
         final WeakListener<ObservableList> mListener;
 
-        public WeakListListener(ViewDataBinding binder, int localFieldId) {
-            mListener = new WeakListener<ObservableList>(binder, localFieldId, this);
+        public WeakListListener(
+                ViewDataBinding binder,
+                int localFieldId,
+                ReferenceQueue<ViewDataBinding> referenceQueue
+        ) {
+            mListener = new WeakListener<ObservableList>(
+                    binder, localFieldId, this, referenceQueue
+            );
         }
 
         @Override
@@ -1535,8 +1521,14 @@
             implements ObservableReference<ObservableMap> {
         final WeakListener<ObservableMap> mListener;
 
-        public WeakMapListener(ViewDataBinding binder, int localFieldId) {
-            mListener = new WeakListener<ObservableMap>(binder, localFieldId, this);
+        public WeakMapListener(
+                ViewDataBinding binder,
+                int localFieldId,
+                ReferenceQueue<ViewDataBinding> referenceQueue
+        ) {
+            mListener = new WeakListener<ObservableMap>(
+                    binder, localFieldId, this, referenceQueue
+            );
         }
 
         @Override
@@ -1573,8 +1565,12 @@
         final WeakListener<LiveData<?>> mListener;
         LifecycleOwner mLifecycleOwner;
 
-        public LiveDataListener(ViewDataBinding binder, int localFieldId) {
-            mListener = new WeakListener(binder, localFieldId, this);
+        public LiveDataListener(
+                ViewDataBinding binder,
+                int localFieldId,
+                ReferenceQueue<ViewDataBinding> referenceQueue
+        ) {
+            mListener = new WeakListener(binder, localFieldId, this, referenceQueue);
         }
 
         @Override
@@ -1618,10 +1614,6 @@
         }
     }
 
-    private interface CreateWeakListener {
-        WeakListener create(ViewDataBinding viewDataBinding, int localFieldId);
-    }
-
     /**
      * This class is used by generated subclasses of {@link ViewDataBinding} to track the
      * included layouts contained in the bound layout. This class is an implementation
diff --git a/extensions/library/src/main/java/androidx/databinding/WeakListener.java b/extensions/library/src/main/java/androidx/databinding/WeakListener.java
new file mode 100644
index 0000000..0af2313
--- /dev/null
+++ b/extensions/library/src/main/java/androidx/databinding/WeakListener.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.databinding;
+
+import android.annotation.TargetApi;
+
+import androidx.annotation.RestrictTo;
+import androidx.lifecycle.Lifecycle;
+import androidx.lifecycle.LifecycleObserver;
+import androidx.lifecycle.LifecycleOwner;
+import androidx.lifecycle.LiveData;
+import androidx.lifecycle.Observer;
+import androidx.lifecycle.OnLifecycleEvent;
+import android.content.res.ColorStateList;
+import androidx.databinding.CallbackRegistry.NotifierCallback;
+import android.graphics.drawable.Drawable;
+import android.os.Build.VERSION;
+import android.os.Build.VERSION_CODES;
+import android.os.Handler;
+import android.os.Looper;
+import androidx.annotation.MainThread;
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+import android.text.TextUtils;
+import android.util.LongSparseArray;
+import android.util.SparseArray;
+import android.util.SparseBooleanArray;
+import android.util.SparseIntArray;
+import android.util.SparseLongArray;
+import android.view.Choreographer;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.View.OnAttachStateChangeListener;
+import android.view.ViewGroup;
+import androidx.viewbinding.ViewBinding;
+
+import androidx.databinding.library.R;
+import androidx.databinding.ObservableReference;
+
+import java.lang.ref.Reference;
+import java.lang.ref.ReferenceQueue;
+import java.lang.ref.WeakReference;
+import java.util.List;
+import java.util.Map;
+
+@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+class WeakListener<T> extends WeakReference<ViewDataBinding> {
+    private final ObservableReference<T> mObservable;
+    protected final int mLocalFieldId;
+    private T mTarget;
+
+    public WeakListener(
+            ViewDataBinding binder,
+            int localFieldId,
+            ObservableReference<T> observable,
+            ReferenceQueue<ViewDataBinding> referenceQueue
+    ) {
+        super(binder, referenceQueue);
+        mLocalFieldId = localFieldId;
+        mObservable = observable;
+    }
+
+    public void setLifecycleOwner(LifecycleOwner lifecycleOwner) {
+        mObservable.setLifecycleOwner(lifecycleOwner);
+    }
+
+    public void setTarget(T object) {
+        unregister();
+        mTarget = object;
+        if (mTarget != null) {
+            mObservable.addListener(mTarget);
+        }
+    }
+
+    public boolean unregister() {
+        boolean unregistered = false;
+        if (mTarget != null) {
+            mObservable.removeListener(mTarget);
+            unregistered = true;
+        }
+        mTarget = null;
+        return unregistered;
+    }
+
+    public T getTarget() {
+        return mTarget;
+    }
+
+    @Nullable
+    protected ViewDataBinding getBinder() {
+        ViewDataBinding binder = get();
+        if (binder == null) {
+            unregister(); // The binder is dead
+        }
+        return binder;
+    }
+}
diff --git a/extensions/settings.gradle b/extensions/settings.gradle
index 90a9cf9..c8e8119 100644
--- a/extensions/settings.gradle
+++ b/extensions/settings.gradle
@@ -20,6 +20,7 @@
 include ':library'
 include ':baseAdapters'
 include ':viewbinding'
+include ':databindingKtx'
 if (hasProperty("includeDoclava")) {
     File externalRoot = new File(rootDir, '../../../external')
     include ':doclava'
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index 59b5f89..5028f28 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,5 +1,5 @@
 distributionBase=GRADLE_USER_HOME
 distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.1-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-bin.zip
 zipStoreBase=GRADLE_USER_HOME
 zipStorePath=wrapper/dists
diff --git a/integration-tests/DynamicApp/app/build.gradle b/integration-tests/DynamicApp/app/build.gradle
index 98bac45..ab7384a 100644
--- a/integration-tests/DynamicApp/app/build.gradle
+++ b/integration-tests/DynamicApp/app/build.gradle
@@ -44,8 +44,8 @@
 
 dependencies {
     api 'androidx.appcompat:appcompat:1.0.0'
-    api 'androidx.lifecycle:lifecycle-extensions:2.0.0'
+    api 'androidx.lifecycle:lifecycle-extensions:2.2.0'
     testImplementation 'junit:junit:4.12'
     androidTestImplementation 'com.android.support.test:runner:1.0.1'
     androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
-}
\ No newline at end of file
+}
diff --git a/integration-tests/KotlinTestApp/app/build.gradle b/integration-tests/KotlinTestApp/app/build.gradle
index 76c4bfe..752b350 100644
--- a/integration-tests/KotlinTestApp/app/build.gradle
+++ b/integration-tests/KotlinTestApp/app/build.gradle
@@ -23,6 +23,7 @@
 apply plugin: 'kotlin-kapt'
 android {
     compileSdkVersion rootProject.latestCompileSdk
+
     defaultConfig {
         applicationId "androidx.databinding.kotlintestapp"
         minSdkVersion 14
@@ -41,14 +42,16 @@
 }
 
 dependencies {
-    def supportVersion = "1.0.0"
-    def lifecycleVersion = "2.0.0"
+    def supportVersion = "1.2.0"
+    def lifecycleVersion = "2.2.0"
     def testingVersion = "1.1.0"
     implementation fileTree(dir: 'libs', include: ['*.jar'])
     implementation project(":library1")
     implementation "org.jetbrains.kotlin:kotlin-stdlib:$rootProject.kotlinVersion"
     implementation "androidx.lifecycle:lifecycle-runtime:$lifecycleVersion"
-    implementation "androidx.lifecycle:lifecycle-livedata:$lifecycleVersion"
+    implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycleVersion"
+    implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycleVersion"
+    implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1"
     implementation "androidx.appcompat:appcompat:$supportVersion"
     testImplementation 'junit:junit:4.12'
     androidTestImplementation("androidx.test:runner:$testingVersion") {
diff --git a/integration-tests/KotlinTestApp/app/src/androidTest/java/androidx/databinding/kotlintestapp/StateFlowTest.kt b/integration-tests/KotlinTestApp/app/src/androidTest/java/androidx/databinding/kotlintestapp/StateFlowTest.kt
new file mode 100644
index 0000000..36a6e8f
--- /dev/null
+++ b/integration-tests/KotlinTestApp/app/src/androidTest/java/androidx/databinding/kotlintestapp/StateFlowTest.kt
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.databinding.kotlintestapp
+
+import androidx.databinding.kotlintestapp.databinding.StateFlowBinding
+import androidx.databinding.kotlintestapp.vo.StateFlowContainer
+import androidx.databinding.kotlintestapp.vo.StateFlowViewModel
+import androidx.test.runner.AndroidJUnit4
+import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.flow.MutableStateFlow
+import org.junit.Assert.assertEquals
+import org.junit.Rule
+import org.junit.Test
+import org.junit.runner.RunWith
+
+@ExperimentalCoroutinesApi
+@RunWith(AndroidJUnit4::class)
+class StateFlowTest {
+
+    @Suppress("MemberVisibilityCanPrivate")
+    @Rule
+    @JvmField
+    val rule = BindingActivityRule<StateFlowBinding>(R.layout.state_flow)
+
+    private val stateFlow = MutableStateFlow("")
+    private val stateFlowHolder = MutableStateFlow(stateFlow)
+    private val stateFlowContainer = StateFlowContainer()
+    private val stateFlowViewModel = StateFlowViewModel()
+
+    @Test
+    fun testStateFlow() {
+        setupView()
+
+        assertEquals("", rule.binding.textView1.text.toString())
+        assertEquals("", rule.binding.included.textView1.text.toString())
+        assertEquals("", rule.binding.textView2.text.toString())
+        assertEquals("", rule.binding.included.textView2.text.toString())
+
+        val stateFlowExpected = "Hello world!"
+        stateFlow.value = stateFlowExpected
+        val containerExpected = "Hi there!"
+        stateFlowContainer.stateFlow.value = containerExpected
+        rule.executePendingBindings()
+
+        assertEquals(stateFlowExpected, rule.binding.textView1.text.toString())
+        assertEquals(stateFlowExpected, rule.binding.included.textView1.text.toString())
+        assertEquals(containerExpected, rule.binding.textView2.text.toString())
+        assertEquals(containerExpected, rule.binding.included.textView2.text.toString())
+    }
+
+    @Test
+    fun noLifecycleOwner() {
+        setupView(includeLifecycle = false)
+
+        assertEquals("", rule.binding.textView1.text.toString())
+        assertEquals("", rule.binding.included.textView1.text.toString())
+        assertEquals("", rule.binding.textView2.text.toString())
+        assertEquals("", rule.binding.included.textView2.text.toString())
+
+        stateFlow.value = "Hello world!"
+        stateFlowContainer.stateFlow.value = "Hi there!"
+        rule.executePendingBindings()
+
+        assertEquals("", rule.binding.textView1.text.toString())
+        assertEquals("", rule.binding.included.textView1.text.toString())
+        assertEquals("", rule.binding.textView2.text.toString())
+        assertEquals("", rule.binding.included.textView2.text.toString())
+    }
+
+    @Test
+    fun testMutableStateFlow() {
+        setupView()
+
+        assertEquals("", rule.binding.textView2.text.toString())
+        assertEquals("", rule.binding.included.textView2.text.toString())
+
+        val expected = "EditText changed"
+        rule.runOnUiThread {
+            rule.binding.editText1.setText(expected)
+        }
+        rule.executePendingBindings()
+
+        assertEquals(expected, rule.binding.textView2.text.toString())
+        assertEquals(expected, rule.binding.included.textView2.text.toString())
+        assertEquals(expected, stateFlowContainer.stateFlow.value)
+    }
+
+    @Test
+    fun stateFlowChanged() {
+        setupView()
+
+        stateFlow.value = "foo"
+        rule.executePendingBindings()
+        assertEquals("foo", rule.binding.textView1.text)
+
+        rule.runOnUiThread {
+            val anotherStateFlow = MutableStateFlow("new value")
+            rule.binding.stateFlow = anotherStateFlow
+            rule.executePendingBindings()
+        }
+
+        assertEquals("new value", rule.binding.textView1.text)
+    }
+
+    @Test
+    fun stateFlowOfStateFlowChanged() {
+        setupView()
+
+        stateFlow.value = "foo"
+        rule.executePendingBindings()
+        assertEquals("foo", rule.binding.textView3.text)
+
+        stateFlow.value = "bar"
+        rule.executePendingBindings()
+        assertEquals("bar", rule.binding.textView3.text)
+
+        rule.runOnUiThread {
+            val anotherStateFlow = MutableStateFlow("new value")
+            stateFlowHolder.value = anotherStateFlow
+            rule.executePendingBindings()
+        }
+
+        assertEquals("new value", rule.binding.textView3.text)
+    }
+
+    @Test
+    fun testStateInOperator() {
+        setupView()
+        assertEquals("Hi there", rule.binding.textView4.text.toString())
+    }
+
+    private fun setupView(includeLifecycle: Boolean = true) {
+        rule.runOnUiThread {
+            rule.binding.apply {
+                if (includeLifecycle) {
+                    lifecycleOwner = rule.activity
+                }
+                stateFlow = this@StateFlowTest.stateFlow
+                stateFlowOfStateFlow = this@StateFlowTest.stateFlowHolder
+                stateFlowContainer = this@StateFlowTest.stateFlowContainer
+                stateFlowViewModel = this@StateFlowTest.stateFlowViewModel
+            }
+        }
+
+        rule.executePendingBindings()
+    }
+}
diff --git a/integration-tests/KotlinTestApp/app/src/main/AndroidManifest.xml b/integration-tests/KotlinTestApp/app/src/main/AndroidManifest.xml
index 364d420..3eaa320 100644
--- a/integration-tests/KotlinTestApp/app/src/main/AndroidManifest.xml
+++ b/integration-tests/KotlinTestApp/app/src/main/AndroidManifest.xml
@@ -36,4 +36,4 @@
         </activity>
     </application>
 
-</manifest>
\ No newline at end of file
+</manifest>
diff --git a/integration-tests/KotlinTestApp/app/src/main/java/androidx/databinding/kotlintestapp/vo/StateFlowContainer.kt b/integration-tests/KotlinTestApp/app/src/main/java/androidx/databinding/kotlintestapp/vo/StateFlowContainer.kt
new file mode 100644
index 0000000..25531fa
--- /dev/null
+++ b/integration-tests/KotlinTestApp/app/src/main/java/androidx/databinding/kotlintestapp/vo/StateFlowContainer.kt
@@ -0,0 +1,23 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.databinding.kotlintestapp.vo
+
+import kotlinx.coroutines.flow.MutableStateFlow
+
+class StateFlowContainer {
+    val stateFlow = MutableStateFlow("")
+}
diff --git a/integration-tests/KotlinTestApp/app/src/main/java/androidx/databinding/kotlintestapp/vo/StateFlowViewModel.kt b/integration-tests/KotlinTestApp/app/src/main/java/androidx/databinding/kotlintestapp/vo/StateFlowViewModel.kt
new file mode 100644
index 0000000..358cb7b
--- /dev/null
+++ b/integration-tests/KotlinTestApp/app/src/main/java/androidx/databinding/kotlintestapp/vo/StateFlowViewModel.kt
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.databinding.kotlintestapp.vo
+
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.viewModelScope
+import kotlinx.coroutines.flow.SharingStarted
+import kotlinx.coroutines.flow.flow
+import kotlinx.coroutines.flow.stateIn
+
+class StateFlowViewModel : ViewModel() {
+
+    val stateFlow = flow {
+        emit("Hi there")
+    }.stateIn(viewModelScope, SharingStarted.WhileSubscribed(), "")
+}
diff --git a/integration-tests/KotlinTestApp/app/src/main/res/layout/adapter_from_library.xml b/integration-tests/KotlinTestApp/app/src/main/res/layout/adapter_from_library.xml
index c301f86..8a354e2 100644
--- a/integration-tests/KotlinTestApp/app/src/main/res/layout/adapter_from_library.xml
+++ b/integration-tests/KotlinTestApp/app/src/main/res/layout/adapter_from_library.xml
@@ -16,4 +16,4 @@
     android:id="@+id/library1TextView"
     app:setTextViaLibrary1="@{text}"/>
   </LinearLayout>
-</layout>
\ No newline at end of file
+</layout>
diff --git a/integration-tests/KotlinTestApp/app/src/main/res/layout/state_flow.xml b/integration-tests/KotlinTestApp/app/src/main/res/layout/state_flow.xml
new file mode 100644
index 0000000..79a0588
--- /dev/null
+++ b/integration-tests/KotlinTestApp/app/src/main/res/layout/state_flow.xml
@@ -0,0 +1,79 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+  ~ Copyright (C) 2020 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<layout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto">
+
+    <data>
+        <variable
+            name="stateFlow"
+            type="kotlinx.coroutines.flow.StateFlow&lt;String&gt;" />
+
+        <variable
+            name="stateFlowOfStateFlow"
+            type="kotlinx.coroutines.flow.StateFlow&lt;kotlinx.coroutines.flow.StateFlow&lt;String&gt;&gt;" />
+
+        <variable
+            name="stateFlowContainer"
+            type="androidx.databinding.kotlintestapp.vo.StateFlowContainer" />
+
+        <variable
+            name="stateFlowViewModel"
+            type="androidx.databinding.kotlintestapp.vo.StateFlowViewModel" />
+    </data>
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:orientation="vertical">
+
+        <TextView
+            android:id="@+id/textView1"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@{stateFlow}" />
+
+        <TextView
+            android:id="@+id/textView2"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@{stateFlowContainer.stateFlow}" />
+
+        <TextView
+            android:id="@+id/textView3"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@{stateFlowOfStateFlow}" />
+
+        <TextView
+            android:id="@+id/textView4"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@{stateFlowViewModel.stateFlow}" />
+
+        <EditText
+            android:id="@+id/editText1"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@={stateFlowContainer.stateFlow}" />
+
+        <include layout="@layout/state_flow_included"
+            android:id="@+id/included"
+            app:stateFlow="@{stateFlow}"
+            app:stateFlowContainer="@{stateFlowContainer}" />
+
+    </LinearLayout>
+</layout>
diff --git a/integration-tests/KotlinTestApp/app/src/main/res/layout/state_flow_included.xml b/integration-tests/KotlinTestApp/app/src/main/res/layout/state_flow_included.xml
new file mode 100644
index 0000000..68c498e
--- /dev/null
+++ b/integration-tests/KotlinTestApp/app/src/main/res/layout/state_flow_included.xml
@@ -0,0 +1,53 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+  ~ Copyright (C) 2020 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<layout xmlns:android="http://schemas.android.com/apk/res/android">
+
+    <data>
+        <variable
+            name="stateFlow"
+            type="kotlinx.coroutines.flow.StateFlow&lt;String&gt;" />
+
+        <variable
+            name="stateFlowContainer"
+            type="androidx.databinding.kotlintestapp.vo.StateFlowContainer" />
+    </data>
+
+    <LinearLayout
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:orientation="vertical">
+
+        <TextView
+            android:id="@+id/textView1"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@{stateFlow}" />
+
+        <TextView
+            android:id="@+id/textView2"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@{stateFlowContainer.stateFlow}" />
+
+        <EditText
+            android:id="@+id/editText1"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="@={stateFlowContainer.stateFlow}" />
+
+    </LinearLayout>
+</layout>
diff --git a/integration-tests/KotlinTestApp/build.gradle b/integration-tests/KotlinTestApp/build.gradle
index ff3a7d1..d499539 100644
--- a/integration-tests/KotlinTestApp/build.gradle
+++ b/integration-tests/KotlinTestApp/build.gradle
@@ -33,4 +33,4 @@
         project.apply from: "../../commonHeader.gradle"
         project.apply from: "../../commonLocalRepo.gradle"
     }
-}
\ No newline at end of file
+}
diff --git a/integration-tests/KotlinTestApp/library1/build.gradle b/integration-tests/KotlinTestApp/library1/build.gradle
index 1fc6a24..2d7055b 100644
--- a/integration-tests/KotlinTestApp/library1/build.gradle
+++ b/integration-tests/KotlinTestApp/library1/build.gradle
@@ -12,13 +12,14 @@
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
- `*/
+ */
 
 apply plugin: 'com.android.library'
 apply plugin: 'kotlin-android'
 apply plugin: 'kotlin-kapt'
 android {
     compileSdkVersion rootProject.latestCompileSdk
+
     defaultConfig {
         minSdkVersion 14
         targetSdkVersion rootProject.latestCompileSdk
diff --git a/integration-tests/TestApp/app/build.gradle b/integration-tests/TestApp/app/build.gradle
index 993d61e..f42560a 100644
--- a/integration-tests/TestApp/app/build.gradle
+++ b/integration-tests/TestApp/app/build.gradle
@@ -32,7 +32,7 @@
 
 dependencies {
     def supportVersion = "1.0.0"
-    def lifecycleVersion = "2.0.0"
+    def lifecycleVersion = "2.2.0"
     implementation fileTree(dir: 'libs', include: ['*.jar'])
     implementation "androidx.annotation:annotation:$supportVersion"
     compileOnly 'javax.annotation:jsr250-api:1.0'
diff --git a/integration-tests/ViewBindingWithDataBindingTestApp/app/build.gradle b/integration-tests/ViewBindingWithDataBindingTestApp/app/build.gradle
index e768a35..d9620cf 100644
--- a/integration-tests/ViewBindingWithDataBindingTestApp/app/build.gradle
+++ b/integration-tests/ViewBindingWithDataBindingTestApp/app/build.gradle
@@ -43,7 +43,7 @@
 
 dependencies {
     def supportVersion = "1.0.0"
-    def lifecycleVersion = "2.0.0"
+    def lifecycleVersion = "2.2.0"
     def testingVersion = "1.1.0"
     implementation fileTree(dir: 'libs', include: ['*.jar'])
     implementation "org.jetbrains.kotlin:kotlin-stdlib:$rootProject.kotlinVersion"