Merge changes from topic "creation_activity" into androidx-main
* changes:
Integrate CreationExtras into ComponentActivity
Provide creation extras to ViewModel lazy
diff --git a/activity/activity-ktx/src/main/java/androidx/activity/ActivityViewModelLazy.kt b/activity/activity-ktx/src/main/java/androidx/activity/ActivityViewModelLazy.kt
index a47e4f5..bf64ade 100644
--- a/activity/activity-ktx/src/main/java/androidx/activity/ActivityViewModelLazy.kt
+++ b/activity/activity-ktx/src/main/java/androidx/activity/ActivityViewModelLazy.kt
@@ -44,5 +44,10 @@
defaultViewModelProviderFactory
}
- return ViewModelLazy(VM::class, { viewModelStore }, factoryPromise)
+ return ViewModelLazy(
+ VM::class,
+ { viewModelStore },
+ factoryPromise,
+ { this.defaultViewModelCreationExtras }
+ )
}
diff --git a/activity/activity/src/androidTest/java/androidx/activity/ComponentActivityViewModelTest.kt b/activity/activity/src/androidTest/java/androidx/activity/ComponentActivityViewModelTest.kt
index 75b5142..33417d3 100644
--- a/activity/activity/src/androidTest/java/androidx/activity/ComponentActivityViewModelTest.kt
+++ b/activity/activity/src/androidTest/java/androidx/activity/ComponentActivityViewModelTest.kt
@@ -107,6 +107,23 @@
assertThat(withActivity { viewModel }).isSameInstanceAs(vm)
}
}
+
+ @Test
+ fun testCreateViewModelViaExtras() {
+ val scenario = ActivityScenario.launch(ViewModelActivity::class.java)
+ with(scenario) {
+ val creationViewModel = withActivity {
+ ViewModelProvider(
+ viewModelStore,
+ defaultViewModelProviderFactory,
+ defaultViewModelCreationExtras)["test", TestViewModel::class.java]
+ }
+ recreate()
+ assertThat(withActivity {
+ ViewModelProvider(this)["test", TestViewModel::class.java]
+ }).isSameInstanceAs(creationViewModel)
+ }
+ }
}
class ViewModelActivity : ComponentActivity() {
diff --git a/activity/activity/src/main/java/androidx/activity/ComponentActivity.java b/activity/activity/src/main/java/androidx/activity/ComponentActivity.java
index 4672265..c2ff337 100644
--- a/activity/activity/src/main/java/androidx/activity/ComponentActivity.java
+++ b/activity/activity/src/main/java/androidx/activity/ComponentActivity.java
@@ -28,6 +28,7 @@
import static androidx.activity.result.contract.ActivityResultContracts.StartIntentSenderForResult.ACTION_INTENT_SENDER_REQUEST;
import static androidx.activity.result.contract.ActivityResultContracts.StartIntentSenderForResult.EXTRA_INTENT_SENDER_REQUEST;
import static androidx.activity.result.contract.ActivityResultContracts.StartIntentSenderForResult.EXTRA_SEND_INTENT_EXCEPTION;
+import static androidx.lifecycle.SavedStateHandleSupport.enableSavedStateHandles;
import android.Manifest;
import android.annotation.SuppressLint;
@@ -81,12 +82,15 @@
import androidx.lifecycle.LifecycleOwner;
import androidx.lifecycle.LifecycleRegistry;
import androidx.lifecycle.ReportFragment;
+import androidx.lifecycle.SavedStateHandleSupport;
import androidx.lifecycle.SavedStateViewModelFactory;
import androidx.lifecycle.ViewModelProvider;
import androidx.lifecycle.ViewModelStore;
import androidx.lifecycle.ViewModelStoreOwner;
import androidx.lifecycle.ViewTreeLifecycleOwner;
import androidx.lifecycle.ViewTreeViewModelStoreOwner;
+import androidx.lifecycle.viewmodel.CreationExtras;
+import androidx.lifecycle.viewmodel.MutableCreationExtras;
import androidx.savedstate.SavedStateRegistry;
import androidx.savedstate.SavedStateRegistryController;
import androidx.savedstate.SavedStateRegistryOwner;
@@ -331,6 +335,7 @@
*/
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
+ enableSavedStateHandles(this);
// Restore the Saved State first so that it is available to
// OnContextAvailableListener instances
mSavedStateRegistryController.performRestore(savedInstanceState);
@@ -573,27 +578,36 @@
}
}
+ @NonNull
+ @Override
+ public ViewModelProvider.Factory getDefaultViewModelProviderFactory() {
+ if (mDefaultFactory == null) {
+ mDefaultFactory = new SavedStateViewModelFactory();
+ }
+ return mDefaultFactory;
+ }
+
/**
* {@inheritDoc}
*
* <p>The extras of {@link #getIntent()} when this is first called will be used as
* the defaults to any {@link androidx.lifecycle.SavedStateHandle} passed to a view model
- * created using this factory.</p>
+ * created using this extra.</p>
*/
@NonNull
@Override
- public ViewModelProvider.Factory getDefaultViewModelProviderFactory() {
- if (getApplication() == null) {
- throw new IllegalStateException("Your activity is not yet attached to the "
- + "Application instance. You can't request ViewModel before onCreate call.");
+ @CallSuper
+ public CreationExtras getDefaultViewModelCreationExtras() {
+ MutableCreationExtras extras = new MutableCreationExtras();
+ if (getApplication() != null) {
+ extras.set(ViewModelProvider.AndroidViewModelFactory.APPLICATION_KEY, getApplication());
}
- if (mDefaultFactory == null) {
- mDefaultFactory = new SavedStateViewModelFactory(
- getApplication(),
- this,
- getIntent() != null ? getIntent().getExtras() : null);
+ extras.set(SavedStateHandleSupport.SAVED_STATE_REGISTRY_OWNER_KEY, this);
+ extras.set(SavedStateHandleSupport.VIEW_MODEL_STORE_OWNER_KEY, this);
+ if (getIntent() != null && getIntent().getExtras() != null) {
+ extras.set(SavedStateHandleSupport.DEFAULT_ARGS_KEY, getIntent().getExtras());
}
- return mDefaultFactory;
+ return extras;
}
/**
diff --git a/fragment/fragment-ktx/api/current.txt b/fragment/fragment-ktx/api/current.txt
index 64ef804..946af54 100644
--- a/fragment/fragment-ktx/api/current.txt
+++ b/fragment/fragment-ktx/api/current.txt
@@ -23,6 +23,7 @@
public final class FragmentViewModelLazyKt {
method @MainThread public static inline <reified VM extends androidx.lifecycle.ViewModel> kotlin.Lazy<? extends VM>! activityViewModels(androidx.fragment.app.Fragment, optional kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelProvider.Factory>? factoryProducer);
method @MainThread public static <VM extends androidx.lifecycle.ViewModel> kotlin.Lazy<VM> createViewModelLazy(androidx.fragment.app.Fragment, kotlin.reflect.KClass<VM> viewModelClass, kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelStore> storeProducer, optional kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelProvider.Factory>? factoryProducer);
+ method @MainThread public static <VM extends androidx.lifecycle.ViewModel> kotlin.Lazy<VM> createViewModelLazy(androidx.fragment.app.Fragment, kotlin.reflect.KClass<VM> viewModelClass, kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelStore> storeProducer, optional kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelProvider.Factory>? factoryProducer, optional kotlin.jvm.functions.Function0<? extends androidx.lifecycle.viewmodel.CreationExtras> extrasProducer);
method @MainThread public static inline <reified VM extends androidx.lifecycle.ViewModel> kotlin.Lazy<? extends VM>! viewModels(androidx.fragment.app.Fragment, optional kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelStoreOwner> ownerProducer, optional kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelProvider.Factory>? factoryProducer);
}
diff --git a/fragment/fragment-ktx/api/public_plus_experimental_current.txt b/fragment/fragment-ktx/api/public_plus_experimental_current.txt
index 64ef804..946af54 100644
--- a/fragment/fragment-ktx/api/public_plus_experimental_current.txt
+++ b/fragment/fragment-ktx/api/public_plus_experimental_current.txt
@@ -23,6 +23,7 @@
public final class FragmentViewModelLazyKt {
method @MainThread public static inline <reified VM extends androidx.lifecycle.ViewModel> kotlin.Lazy<? extends VM>! activityViewModels(androidx.fragment.app.Fragment, optional kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelProvider.Factory>? factoryProducer);
method @MainThread public static <VM extends androidx.lifecycle.ViewModel> kotlin.Lazy<VM> createViewModelLazy(androidx.fragment.app.Fragment, kotlin.reflect.KClass<VM> viewModelClass, kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelStore> storeProducer, optional kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelProvider.Factory>? factoryProducer);
+ method @MainThread public static <VM extends androidx.lifecycle.ViewModel> kotlin.Lazy<VM> createViewModelLazy(androidx.fragment.app.Fragment, kotlin.reflect.KClass<VM> viewModelClass, kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelStore> storeProducer, optional kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelProvider.Factory>? factoryProducer, optional kotlin.jvm.functions.Function0<? extends androidx.lifecycle.viewmodel.CreationExtras> extrasProducer);
method @MainThread public static inline <reified VM extends androidx.lifecycle.ViewModel> kotlin.Lazy<? extends VM>! viewModels(androidx.fragment.app.Fragment, optional kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelStoreOwner> ownerProducer, optional kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelProvider.Factory>? factoryProducer);
}
diff --git a/fragment/fragment-ktx/api/restricted_current.txt b/fragment/fragment-ktx/api/restricted_current.txt
index 64ef804..946af54 100644
--- a/fragment/fragment-ktx/api/restricted_current.txt
+++ b/fragment/fragment-ktx/api/restricted_current.txt
@@ -23,6 +23,7 @@
public final class FragmentViewModelLazyKt {
method @MainThread public static inline <reified VM extends androidx.lifecycle.ViewModel> kotlin.Lazy<? extends VM>! activityViewModels(androidx.fragment.app.Fragment, optional kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelProvider.Factory>? factoryProducer);
method @MainThread public static <VM extends androidx.lifecycle.ViewModel> kotlin.Lazy<VM> createViewModelLazy(androidx.fragment.app.Fragment, kotlin.reflect.KClass<VM> viewModelClass, kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelStore> storeProducer, optional kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelProvider.Factory>? factoryProducer);
+ method @MainThread public static <VM extends androidx.lifecycle.ViewModel> kotlin.Lazy<VM> createViewModelLazy(androidx.fragment.app.Fragment, kotlin.reflect.KClass<VM> viewModelClass, kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelStore> storeProducer, optional kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelProvider.Factory>? factoryProducer, optional kotlin.jvm.functions.Function0<? extends androidx.lifecycle.viewmodel.CreationExtras> extrasProducer);
method @MainThread public static inline <reified VM extends androidx.lifecycle.ViewModel> kotlin.Lazy<? extends VM>! viewModels(androidx.fragment.app.Fragment, optional kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelStoreOwner> ownerProducer, optional kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelProvider.Factory>? factoryProducer);
}
diff --git a/fragment/fragment-ktx/src/androidTest/java/androidx/fragment/app/FragmentViewModelLazyTest.kt b/fragment/fragment-ktx/src/androidTest/java/androidx/fragment/app/FragmentViewModelLazyTest.kt
index 09985cc..295e15cd 100644
--- a/fragment/fragment-ktx/src/androidTest/java/androidx/fragment/app/FragmentViewModelLazyTest.kt
+++ b/fragment/fragment-ktx/src/androidTest/java/androidx/fragment/app/FragmentViewModelLazyTest.kt
@@ -19,16 +19,21 @@
import android.os.Bundle
import androidx.activity.viewModels
import androidx.core.os.bundleOf
+import androidx.lifecycle.DEFAULT_ARGS_KEY
+import androidx.lifecycle.SAVED_STATE_REGISTRY_OWNER_KEY
import androidx.lifecycle.SavedStateHandle
import androidx.lifecycle.SavedStateViewModelFactory
+import androidx.lifecycle.VIEW_MODEL_STORE_OWNER_KEY
import androidx.lifecycle.ViewModel
import androidx.lifecycle.ViewModelProvider
+import androidx.lifecycle.enableSavedStateHandles
+import androidx.lifecycle.viewmodel.CreationExtras
+import androidx.lifecycle.viewmodel.MutableCreationExtras
import androidx.test.annotation.UiThreadTest
import androidx.test.filters.MediumTest
import com.google.common.truth.Truth.assertThat
import org.junit.Rule
import org.junit.Test
-import java.lang.IllegalArgumentException
@MediumTest
class FragmentViewModelLazyTest {
@@ -67,12 +72,22 @@
val vm: TestActivityViewModel by viewModels()
val vm2: TestActivityViewModel2 by viewModels()
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ enableSavedStateHandles()
+ }
+
override fun getDefaultViewModelProviderFactory(): ViewModelProvider.Factory {
- return SavedStateViewModelFactory(
- application,
- this,
- bundleOf("test" to "value")
- )
+ return SavedStateViewModelFactory()
+ }
+
+ override fun getDefaultViewModelCreationExtras(): CreationExtras {
+ val extras = MutableCreationExtras()
+ extras[ViewModelProvider.AndroidViewModelFactory.APPLICATION_KEY] = application
+ extras[SAVED_STATE_REGISTRY_OWNER_KEY] = this
+ extras[VIEW_MODEL_STORE_OWNER_KEY] = this
+ extras[DEFAULT_ARGS_KEY] = bundleOf("test" to "value")
+ return extras
}
}
diff --git a/fragment/fragment-ktx/src/main/java/androidx/fragment/app/FragmentViewModelLazy.kt b/fragment/fragment-ktx/src/main/java/androidx/fragment/app/FragmentViewModelLazy.kt
index f42d0400..e281eef 100644
--- a/fragment/fragment-ktx/src/main/java/androidx/fragment/app/FragmentViewModelLazy.kt
+++ b/fragment/fragment-ktx/src/main/java/androidx/fragment/app/FragmentViewModelLazy.kt
@@ -24,6 +24,7 @@
import androidx.lifecycle.ViewModelProvider.Factory
import androidx.lifecycle.ViewModelStore
import androidx.lifecycle.ViewModelStoreOwner
+import androidx.lifecycle.viewmodel.CreationExtras
import kotlin.reflect.KClass
/**
@@ -56,13 +57,19 @@
public inline fun <reified VM : ViewModel> Fragment.viewModels(
noinline ownerProducer: () -> ViewModelStoreOwner = { this },
noinline factoryProducer: (() -> Factory)? = null
-): Lazy<VM> = createViewModelLazy(
- VM::class, { ownerProducer().viewModelStore },
- factoryProducer ?: {
- (ownerProducer() as? HasDefaultViewModelProviderFactory)?.defaultViewModelProviderFactory
- ?: defaultViewModelProviderFactory
+): Lazy<VM> {
+ val owner by lazy(LazyThreadSafetyMode.NONE) { ownerProducer() }
+ return createViewModelLazy(
+ VM::class,
+ { owner.viewModelStore },
+ factoryProducer ?: {
+ (owner as? HasDefaultViewModelProviderFactory)?.defaultViewModelProviderFactory
+ ?: defaultViewModelProviderFactory
+ }) {
+ (owner as? HasDefaultViewModelProviderFactory)?.defaultViewModelCreationExtras
+ ?: CreationExtras.Empty
}
-)
+}
/**
* Returns a property delegate to access parent activity's [ViewModel],
@@ -85,7 +92,8 @@
noinline factoryProducer: (() -> Factory)? = null
): Lazy<VM> = createViewModelLazy(
VM::class, { requireActivity().viewModelStore },
- factoryProducer ?: { requireActivity().defaultViewModelProviderFactory }
+ factoryProducer ?: { requireActivity().defaultViewModelProviderFactory },
+ { requireActivity().defaultViewModelCreationExtras }
)
/**
@@ -97,9 +105,28 @@
viewModelClass: KClass<VM>,
storeProducer: () -> ViewModelStore,
factoryProducer: (() -> Factory)? = null
+): Lazy<VM> = createViewModelLazy(
+ viewModelClass,
+ storeProducer,
+ factoryProducer
+) { defaultViewModelCreationExtras }
+
+/**
+ * Helper method for creation of [ViewModelLazy], that resolves `null` passed as [factoryProducer]
+ * to default factory.
+ *
+ * This method also takes an [CreationExtras] produces that provides default extras to the created
+ * view model.
+ */
+@MainThread
+public fun <VM : ViewModel> Fragment.createViewModelLazy(
+ viewModelClass: KClass<VM>,
+ storeProducer: () -> ViewModelStore,
+ factoryProducer: (() -> Factory)? = null,
+ extrasProducer: () -> CreationExtras = { defaultViewModelCreationExtras }
): Lazy<VM> {
val factoryPromise = factoryProducer ?: {
defaultViewModelProviderFactory
}
- return ViewModelLazy(viewModelClass, storeProducer, factoryPromise)
-}
\ No newline at end of file
+ return ViewModelLazy(viewModelClass, storeProducer, factoryPromise, extrasProducer)
+}
diff --git a/lifecycle/lifecycle-viewmodel/api/current.txt b/lifecycle/lifecycle-viewmodel/api/current.txt
index 996e061..73f1682 100644
--- a/lifecycle/lifecycle-viewmodel/api/current.txt
+++ b/lifecycle/lifecycle-viewmodel/api/current.txt
@@ -17,6 +17,7 @@
}
public final class ViewModelLazy<VM extends androidx.lifecycle.ViewModel> implements kotlin.Lazy<VM> {
+ ctor public ViewModelLazy(kotlin.reflect.KClass<VM> viewModelClass, kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelStore> storeProducer, kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelProvider.Factory> factoryProducer, optional kotlin.jvm.functions.Function0<? extends androidx.lifecycle.viewmodel.CreationExtras> extrasProducer);
ctor public ViewModelLazy(kotlin.reflect.KClass<VM> viewModelClass, kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelStore> storeProducer, kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelProvider.Factory> factoryProducer);
method public VM getValue();
method public boolean isInitialized();
diff --git a/lifecycle/lifecycle-viewmodel/api/public_plus_experimental_current.txt b/lifecycle/lifecycle-viewmodel/api/public_plus_experimental_current.txt
index 996e061..73f1682 100644
--- a/lifecycle/lifecycle-viewmodel/api/public_plus_experimental_current.txt
+++ b/lifecycle/lifecycle-viewmodel/api/public_plus_experimental_current.txt
@@ -17,6 +17,7 @@
}
public final class ViewModelLazy<VM extends androidx.lifecycle.ViewModel> implements kotlin.Lazy<VM> {
+ ctor public ViewModelLazy(kotlin.reflect.KClass<VM> viewModelClass, kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelStore> storeProducer, kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelProvider.Factory> factoryProducer, optional kotlin.jvm.functions.Function0<? extends androidx.lifecycle.viewmodel.CreationExtras> extrasProducer);
ctor public ViewModelLazy(kotlin.reflect.KClass<VM> viewModelClass, kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelStore> storeProducer, kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelProvider.Factory> factoryProducer);
method public VM getValue();
method public boolean isInitialized();
diff --git a/lifecycle/lifecycle-viewmodel/api/restricted_current.txt b/lifecycle/lifecycle-viewmodel/api/restricted_current.txt
index 996e061..73f1682 100644
--- a/lifecycle/lifecycle-viewmodel/api/restricted_current.txt
+++ b/lifecycle/lifecycle-viewmodel/api/restricted_current.txt
@@ -17,6 +17,7 @@
}
public final class ViewModelLazy<VM extends androidx.lifecycle.ViewModel> implements kotlin.Lazy<VM> {
+ ctor public ViewModelLazy(kotlin.reflect.KClass<VM> viewModelClass, kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelStore> storeProducer, kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelProvider.Factory> factoryProducer, optional kotlin.jvm.functions.Function0<? extends androidx.lifecycle.viewmodel.CreationExtras> extrasProducer);
ctor public ViewModelLazy(kotlin.reflect.KClass<VM> viewModelClass, kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelStore> storeProducer, kotlin.jvm.functions.Function0<? extends androidx.lifecycle.ViewModelProvider.Factory> factoryProducer);
method public VM getValue();
method public boolean isInitialized();
diff --git a/lifecycle/lifecycle-viewmodel/src/main/java/androidx/lifecycle/ViewModelLazy.kt b/lifecycle/lifecycle-viewmodel/src/main/java/androidx/lifecycle/ViewModelLazy.kt
index 1e29d7f..88cd92e 100644
--- a/lifecycle/lifecycle-viewmodel/src/main/java/androidx/lifecycle/ViewModelLazy.kt
+++ b/lifecycle/lifecycle-viewmodel/src/main/java/androidx/lifecycle/ViewModelLazy.kt
@@ -16,6 +16,7 @@
package androidx.lifecycle
+import androidx.lifecycle.viewmodel.CreationExtras
import kotlin.reflect.KClass
/**
@@ -27,11 +28,15 @@
*
* [factoryProducer] is a lambda that will be called during initialization,
* returned [ViewModelProvider.Factory] will be used for creation of [VM]
+ *
+ * [providerOwner] is a lambda that will be called during initialization,
+ * returned [HasDefaultViewModelProviderFactory] will get [CreationExtras] used for creation of [VM]
*/
-public class ViewModelLazy<VM : ViewModel> (
+public class ViewModelLazy<VM : ViewModel> @JvmOverloads constructor(
private val viewModelClass: KClass<VM>,
private val storeProducer: () -> ViewModelStore,
- private val factoryProducer: () -> ViewModelProvider.Factory
+ private val factoryProducer: () -> ViewModelProvider.Factory,
+ private val extrasProducer: () -> CreationExtras = { CreationExtras.Empty }
) : Lazy<VM> {
private var cached: VM? = null
@@ -41,7 +46,11 @@
return if (viewModel == null) {
val factory = factoryProducer()
val store = storeProducer()
- ViewModelProvider(store, factory).get(viewModelClass.java).also {
+ ViewModelProvider(
+ store,
+ factory,
+ extrasProducer()
+ ).get(viewModelClass.java).also {
cached = it
}
} else {