Allow ViewModelStoreOwner to provide a default Factory
Use a default method to allow ViewModelStoreOwners to
optionally set a default ViewModelProvider.Factory that
can be used with new, concise ViewModelProvider
constructors.
Test: new tests pass
BUG: 110936593
Change-Id: Ie15b6ebb119f1f7bcbbbdb5209024fddf3452538
diff --git a/lifecycle/lifecycle-viewmodel/api/2.2.0-alpha02.txt b/lifecycle/lifecycle-viewmodel/api/2.2.0-alpha02.txt
index 1c69a2a..dff8f71 100644
--- a/lifecycle/lifecycle-viewmodel/api/2.2.0-alpha02.txt
+++ b/lifecycle/lifecycle-viewmodel/api/2.2.0-alpha02.txt
@@ -12,6 +12,7 @@
}
public class ViewModelProvider {
+ ctor public ViewModelProvider(androidx.lifecycle.ViewModelStoreOwner);
ctor public ViewModelProvider(androidx.lifecycle.ViewModelStoreOwner, androidx.lifecycle.ViewModelProvider.Factory);
ctor public ViewModelProvider(androidx.lifecycle.ViewModelStore, androidx.lifecycle.ViewModelProvider.Factory);
method @MainThread public <T extends androidx.lifecycle.ViewModel> T get(Class<T!>);
@@ -38,6 +39,7 @@
}
public interface ViewModelStoreOwner {
+ method public default androidx.lifecycle.ViewModelProvider.Factory getDefaultViewModelProviderFactory();
method public androidx.lifecycle.ViewModelStore getViewModelStore();
}
diff --git a/lifecycle/lifecycle-viewmodel/api/current.txt b/lifecycle/lifecycle-viewmodel/api/current.txt
index 1c69a2a..dff8f71 100644
--- a/lifecycle/lifecycle-viewmodel/api/current.txt
+++ b/lifecycle/lifecycle-viewmodel/api/current.txt
@@ -12,6 +12,7 @@
}
public class ViewModelProvider {
+ ctor public ViewModelProvider(androidx.lifecycle.ViewModelStoreOwner);
ctor public ViewModelProvider(androidx.lifecycle.ViewModelStoreOwner, androidx.lifecycle.ViewModelProvider.Factory);
ctor public ViewModelProvider(androidx.lifecycle.ViewModelStore, androidx.lifecycle.ViewModelProvider.Factory);
method @MainThread public <T extends androidx.lifecycle.ViewModel> T get(Class<T!>);
@@ -38,6 +39,7 @@
}
public interface ViewModelStoreOwner {
+ method public default androidx.lifecycle.ViewModelProvider.Factory getDefaultViewModelProviderFactory();
method public androidx.lifecycle.ViewModelStore getViewModelStore();
}
diff --git a/lifecycle/lifecycle-viewmodel/src/main/java/androidx/lifecycle/ViewModelProvider.java b/lifecycle/lifecycle-viewmodel/src/main/java/androidx/lifecycle/ViewModelProvider.java
index 56d9f1b..0fd77ff 100644
--- a/lifecycle/lifecycle-viewmodel/src/main/java/androidx/lifecycle/ViewModelProvider.java
+++ b/lifecycle/lifecycle-viewmodel/src/main/java/androidx/lifecycle/ViewModelProvider.java
@@ -82,6 +82,20 @@
private final ViewModelStore mViewModelStore;
/**
+ * Creates {@code ViewModelProvider}, which will create {@code ViewModels} via the
+ * {@link ViewModelStoreOwner#getDefaultViewModelProviderFactory() default factory}
+ * and retain them in a store of the given {@code ViewModelStoreOwner}.
+ *
+ * @param owner a {@code ViewModelStoreOwner} whose {@link ViewModelStore} will be used to
+ * retain {@code ViewModels}. The
+ * {@link ViewModelStoreOwner#getDefaultViewModelProviderFactory() default factory}
+ * will be used to create {@code ViewModels}.
+ */
+ public ViewModelProvider(@NonNull ViewModelStoreOwner owner) {
+ this(owner.getViewModelStore(), owner.getDefaultViewModelProviderFactory());
+ }
+
+ /**
* Creates {@code ViewModelProvider}, which will create {@code ViewModels} via the given
* {@code Factory} and retain them in a store of the given {@code ViewModelStoreOwner}.
*
@@ -172,6 +186,21 @@
*/
public static class NewInstanceFactory implements Factory {
+ private static NewInstanceFactory sInstance;
+
+ /**
+ * Retrieve a singleton instance of NewInstanceFactory.
+ *
+ * @return A valid {@link NewInstanceFactory}
+ */
+ @NonNull
+ static NewInstanceFactory getInstance() {
+ if (sInstance == null) {
+ sInstance = new NewInstanceFactory();
+ }
+ return sInstance;
+ }
+
@SuppressWarnings("ClassNewInstance")
@NonNull
@Override
diff --git a/lifecycle/lifecycle-viewmodel/src/main/java/androidx/lifecycle/ViewModelStoreOwner.java b/lifecycle/lifecycle-viewmodel/src/main/java/androidx/lifecycle/ViewModelStoreOwner.java
index d9bec9f..a92ecdb 100644
--- a/lifecycle/lifecycle-viewmodel/src/main/java/androidx/lifecycle/ViewModelStoreOwner.java
+++ b/lifecycle/lifecycle-viewmodel/src/main/java/androidx/lifecycle/ViewModelStoreOwner.java
@@ -34,4 +34,16 @@
*/
@NonNull
ViewModelStore getViewModelStore();
+
+ /**
+ * Returns the default {@link ViewModelProvider.Factory} that should be
+ * used when no custom {@code Factory} is provided to the
+ * {@link ViewModelProvider} constructors.
+ *
+ * @return a {@code ViewModelProvider.Factory}
+ */
+ @NonNull
+ default ViewModelProvider.Factory getDefaultViewModelProviderFactory() {
+ return ViewModelProvider.NewInstanceFactory.getInstance();
+ }
}
diff --git a/lifecycle/lifecycle-viewmodel/src/test/java/androidx/lifecycle/ViewModelProviderTest.java b/lifecycle/lifecycle-viewmodel/src/test/java/androidx/lifecycle/ViewModelProviderTest.java
index dd9470f..7c86e00 100644
--- a/lifecycle/lifecycle-viewmodel/src/test/java/androidx/lifecycle/ViewModelProviderTest.java
+++ b/lifecycle/lifecycle-viewmodel/src/test/java/androidx/lifecycle/ViewModelProviderTest.java
@@ -85,6 +85,44 @@
}
@Test
+ public void testDefaultFactory() {
+ final ViewModelStore store = new ViewModelStore();
+ ViewModelStoreOwner owner = new ViewModelStoreOwner() {
+ @NonNull
+ @Override
+ public ViewModelStore getViewModelStore() {
+ return store;
+ }
+ };
+ ViewModelProvider provider = new ViewModelProvider(owner);
+ ViewModel1 viewModel = provider.get(ViewModel1.class);
+ assertThat(viewModel, is(provider.get(ViewModel1.class)));
+ }
+
+ @Test
+ public void testCustomDefaultFactory() {
+ final ViewModelStore store = new ViewModelStore();
+ final CountingFactory factory = new CountingFactory();
+ ViewModelStoreOwner owner = new ViewModelStoreOwner() {
+ @NonNull
+ @Override
+ public ViewModelStore getViewModelStore() {
+ return store;
+ }
+
+ @NonNull
+ @Override
+ public ViewModelProvider.Factory getDefaultViewModelProviderFactory() {
+ return factory;
+ }
+ };
+ ViewModelProvider provider = new ViewModelProvider(owner);
+ ViewModel1 viewModel = provider.get(ViewModel1.class);
+ assertThat(viewModel, is(provider.get(ViewModel1.class)));
+ assertThat(factory.mCalled, is(1));
+ }
+
+ @Test
public void testKeyedFactory() {
final ViewModelStore store = new ViewModelStore();
ViewModelStoreOwner owner = new ViewModelStoreOwner() {
@@ -118,4 +156,15 @@
public static class ViewModel2 extends ViewModel {
}
+
+ public static class CountingFactory extends NewInstanceFactory {
+ int mCalled = 0;
+
+ @Override
+ @NonNull
+ public <T extends ViewModel> T create(@NonNull Class<T> modelClass) {
+ mCalled++;
+ return super.create(modelClass);
+ }
+ }
}