Skip to content

Commit

Permalink
Rewrite ViewModelProvider to kotlin
Browse files Browse the repository at this point in the history
Test: Existing tests pass
Relnote: """*Source-breaking change* ViewModelProvider was written to Kotlin.
    `ViewModelProvider.Factory.create` method doesn't allow nullable
    generics anymore.
    """
Change-Id: I9b9f6617dc9377bc99a954eb096194b1240c98fe
  • Loading branch information
Sergey Vasilinets committed Jun 24, 2021
1 parent ce18bf2 commit 927300f
Show file tree
Hide file tree
Showing 23 changed files with 277 additions and 235 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ private object InteropArchitectureSnippet1 {

class GreetingViewModelFactory(private val userId: String) : ViewModelProvider.Factory {
@Suppress("UNCHECKED_CAST")
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
override fun <T : ViewModel> create(modelClass: Class<T>): T {
return GreetingViewModel(userId) as T
}
}
Expand Down Expand Up @@ -211,7 +211,7 @@ private class GreetingViewModel(userId: String) : ViewModel() {
}
private class GreetingViewModelFactory(private val userId: String) : ViewModelProvider.Factory {
@Suppress("UNCHECKED_CAST")
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
override fun <T : ViewModel> create(modelClass: Class<T>): T {
return GreetingViewModel(userId) as T
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ class FragmentScenarioViewModelTest {
`when`(mockViewModel.getUserName()).thenReturn(fakeUserName)
val viewModelFactory = object : ViewModelProvider.NewInstanceFactory() {
@Suppress("UNCHECKED_CAST")
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
override fun <T : ViewModel> create(modelClass: Class<T>): T {
return when (modelClass) {
InjectedViewModel::class.java -> mockViewModel as T
else -> super.create(modelClass)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -293,7 +293,7 @@ public class FragmentScenario<F : Fragment> private constructor(
internal val FACTORY: ViewModelProvider.Factory =
object : ViewModelProvider.Factory {
@Suppress("UNCHECKED_CAST")
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
override fun <T : ViewModel> create(modelClass: Class<T>): T {
val viewModel =
FragmentFactoryHolderViewModel()
return viewModel as T
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ class FragmentViewLifecycleOwnerTest {

class FakeViewModelProviderFactory : ViewModelProvider.Factory {
private var createCalled: Boolean = false
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
override fun <T : ViewModel> create(modelClass: Class<T>): T {
require(modelClass == TestViewModel::class.java)
createCalled = true
@Suppress("UNCHECKED_CAST")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ class ViewModelProvidersFragmentTest {
class CountingFactory : ViewModelProvider.NewInstanceFactory() {
var count = 0

override fun <T : ViewModel?> create(modelClass: Class<T>): T {
override fun <T : ViewModel> create(modelClass: Class<T>): T {
count++
return super.create(modelClass)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ private class TestViewModel : ViewModel()

private class FakeViewModelProviderFactory : ViewModelProvider.Factory {
var createCalled = false
override fun <T : ViewModel?> create(modelClass: Class<T>): T {
override fun <T : ViewModel> create(modelClass: Class<T>): T {
require(modelClass == TestViewModel::class.java)
createCalled = true
@Suppress("UNCHECKED_CAST")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
* limitations under the License.
*/

@file:JvmName("ViewModelProviderKt")
package androidx.lifecycle

import androidx.annotation.MainThread
Expand Down Expand Up @@ -60,4 +61,4 @@ public class ViewModelLazy<VM : ViewModel> (
}

override fun isInitialized(): Boolean = cached != null
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ class ViewModelLazyTest {

@Suppress("UNCHECKED_CAST")
class TestFactory : ViewModelProvider.Factory {
override fun <T : ViewModel?> create(modelClass: Class<T>): T = TestVM("spb") as T

override fun <T : ViewModel> create(modelClass: Class<T>): T = TestVM("spb") as T
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
// Baseline format: 1.0
RemovedInterface: androidx.lifecycle.AbstractSavedStateViewModelFactory:
Class androidx.lifecycle.AbstractSavedStateViewModelFactory no longer implements androidx.lifecycle.ViewModelProvider.Factory
RemovedInterface: androidx.lifecycle.SavedStateViewModelFactory:
Class androidx.lifecycle.SavedStateViewModelFactory no longer implements androidx.lifecycle.ViewModelProvider.Factory


RemovedMethod: androidx.lifecycle.SavedStateViewModelFactory#create(Class<T>):
Removed method androidx.lifecycle.SavedStateViewModelFactory.create(Class<T>)
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Signature format: 4.0
package androidx.lifecycle {

public abstract class AbstractSavedStateViewModelFactory implements androidx.lifecycle.ViewModelProvider.Factory {
public abstract class AbstractSavedStateViewModelFactory extends androidx.lifecycle.ViewModelProvider.KeyedFactory {
ctor public AbstractSavedStateViewModelFactory(androidx.savedstate.SavedStateRegistryOwner, android.os.Bundle?);
method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP) public final <T extends androidx.lifecycle.ViewModel> T create(String, Class<T!>);
method public final <T extends androidx.lifecycle.ViewModel> T create(Class<T!>);
Expand All @@ -22,11 +22,10 @@ package androidx.lifecycle {
method @MainThread public void setSavedStateProvider(String, androidx.savedstate.SavedStateRegistry.SavedStateProvider);
}

public final class SavedStateViewModelFactory implements androidx.lifecycle.ViewModelProvider.Factory {
public final class SavedStateViewModelFactory extends androidx.lifecycle.ViewModelProvider.KeyedFactory {
ctor public SavedStateViewModelFactory(android.app.Application?, androidx.savedstate.SavedStateRegistryOwner);
ctor public SavedStateViewModelFactory(android.app.Application?, androidx.savedstate.SavedStateRegistryOwner, android.os.Bundle?);
method public <T extends androidx.lifecycle.ViewModel> T create(String, Class<T!>);
method public <T extends androidx.lifecycle.ViewModel> T create(Class<T!>);
}

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ class SavedStateFactoryTest {
val savedStateVMFactory = object : AbstractSavedStateViewModelFactory(
activity, null
) {
override fun <T : ViewModel?> create(
override fun <T : ViewModel> create(
key: String,
modelClass: Class<T>,
handle: SavedStateHandle
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ class ViewModelsWithStateTest(private val mode: Mode) {
SavedStateViewModelFactory(activity.application, savedStateOwner) as Factory
} else {
object : AbstractSavedStateViewModelFactory(savedStateOwner, null) {
override fun <T : ViewModel?> create(
override fun <T : ViewModel> create(
key: String,
modelClass: Class<T>,
handle: SavedStateHandle
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,12 @@ public final <T extends ViewModel> T create(@NonNull Class<T> modelClass) {
protected abstract <T extends ViewModel> T create(@NonNull String key,
@NonNull Class<T> modelClass, @NonNull SavedStateHandle handle);

/**
* @hide
*/
@Override
void onRequery(@NonNull ViewModel viewModel) {
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
public void onRequery(@NonNull ViewModel viewModel) {
attachHandleIfNeeded(viewModel, mSavedStateRegistry, mLifecycle);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RestrictTo;
import androidx.savedstate.SavedStateRegistry;
import androidx.savedstate.SavedStateRegistryOwner;

Expand Down Expand Up @@ -162,8 +163,12 @@ private static <T> Constructor<T> findMatchingConstructor(Class<T> modelClass,
return null;
}

/**
* @hide
*/
@Override
void onRequery(@NonNull ViewModel viewModel) {
@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
public void onRequery(@NonNull ViewModel viewModel) {
attachHandleIfNeeded(viewModel, mSavedStateRegistry, mLifecycle);
}
}
8 changes: 4 additions & 4 deletions lifecycle/lifecycle-viewmodel/api/api_lint.ignore
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
// Baseline format: 1.0
KotlinOperator: androidx.lifecycle.ViewModelProvider#get(Class<T>):
Method can be invoked with an indexing operator from Kotlin: `get` (this is usually desirable; just make sure it makes sense for this type of object)
KotlinOperator: androidx.lifecycle.ViewModelProvider#get(String, Class<T>):
Method can be invoked with an indexing operator from Kotlin: `get` (this is usually desirable; just make sure it makes sense for this type of object)
MissingJvmstatic: androidx.lifecycle.ViewModelProvider.NewInstanceFactory#instance:
Companion object constants like instance should be using @JvmField, not @JvmStatic; see https://developer.android.com/kotlin/interop#companion_constants


SingletonConstructor: androidx.lifecycle.ViewModelProvider.AndroidViewModelFactory#AndroidViewModelFactory(android.app.Application):
Singleton classes should use `getInstance()` methods: `AndroidViewModelFactory`
SingletonConstructor: androidx.lifecycle.ViewModelProvider.NewInstanceFactory#NewInstanceFactory():
Singleton classes should use `getInstance()` methods: `NewInstanceFactory`
27 changes: 18 additions & 9 deletions lifecycle/lifecycle-viewmodel/api/current.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,25 +16,34 @@ package androidx.lifecycle {
}

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!>);
method @MainThread public <T extends androidx.lifecycle.ViewModel> T get(String, Class<T!>);
ctor public ViewModelProvider(androidx.lifecycle.ViewModelStore store, androidx.lifecycle.ViewModelProvider.Factory factory);
ctor public ViewModelProvider(androidx.lifecycle.ViewModelStoreOwner owner);
ctor public ViewModelProvider(androidx.lifecycle.ViewModelStoreOwner owner, androidx.lifecycle.ViewModelProvider.Factory factory);
method @MainThread public operator <T extends androidx.lifecycle.ViewModel> T get(Class<T> modelClass);
method @MainThread public operator <T extends androidx.lifecycle.ViewModel> T get(String key, Class<T> modelClass);
}

public static class ViewModelProvider.AndroidViewModelFactory extends androidx.lifecycle.ViewModelProvider.NewInstanceFactory {
ctor public ViewModelProvider.AndroidViewModelFactory(android.app.Application);
method public static androidx.lifecycle.ViewModelProvider.AndroidViewModelFactory getInstance(android.app.Application);
ctor public ViewModelProvider.AndroidViewModelFactory(android.app.Application application);
method public static final androidx.lifecycle.ViewModelProvider.AndroidViewModelFactory getInstance(android.app.Application application);
field public static final androidx.lifecycle.ViewModelProvider.AndroidViewModelFactory.Companion Companion;
}

public static final class ViewModelProvider.AndroidViewModelFactory.Companion {
method public androidx.lifecycle.ViewModelProvider.AndroidViewModelFactory getInstance(android.app.Application application);
}

public static interface ViewModelProvider.Factory {
method public <T extends androidx.lifecycle.ViewModel> T create(Class<T!>);
method public <T extends androidx.lifecycle.ViewModel> T create(Class<T> modelClass);
}

public static class ViewModelProvider.NewInstanceFactory implements androidx.lifecycle.ViewModelProvider.Factory {
ctor public ViewModelProvider.NewInstanceFactory();
method public <T extends androidx.lifecycle.ViewModel> T create(Class<T!>);
method public <T extends androidx.lifecycle.ViewModel> T create(Class<T> modelClass);
field public static final androidx.lifecycle.ViewModelProvider.NewInstanceFactory.Companion Companion;
}

public static final class ViewModelProvider.NewInstanceFactory.Companion {
}

public class ViewModelStore {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,25 +16,34 @@ package androidx.lifecycle {
}

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!>);
method @MainThread public <T extends androidx.lifecycle.ViewModel> T get(String, Class<T!>);
ctor public ViewModelProvider(androidx.lifecycle.ViewModelStore store, androidx.lifecycle.ViewModelProvider.Factory factory);
ctor public ViewModelProvider(androidx.lifecycle.ViewModelStoreOwner owner);
ctor public ViewModelProvider(androidx.lifecycle.ViewModelStoreOwner owner, androidx.lifecycle.ViewModelProvider.Factory factory);
method @MainThread public operator <T extends androidx.lifecycle.ViewModel> T get(Class<T> modelClass);
method @MainThread public operator <T extends androidx.lifecycle.ViewModel> T get(String key, Class<T> modelClass);
}

public static class ViewModelProvider.AndroidViewModelFactory extends androidx.lifecycle.ViewModelProvider.NewInstanceFactory {
ctor public ViewModelProvider.AndroidViewModelFactory(android.app.Application);
method public static androidx.lifecycle.ViewModelProvider.AndroidViewModelFactory getInstance(android.app.Application);
ctor public ViewModelProvider.AndroidViewModelFactory(android.app.Application application);
method public static final androidx.lifecycle.ViewModelProvider.AndroidViewModelFactory getInstance(android.app.Application application);
field public static final androidx.lifecycle.ViewModelProvider.AndroidViewModelFactory.Companion Companion;
}

public static final class ViewModelProvider.AndroidViewModelFactory.Companion {
method public androidx.lifecycle.ViewModelProvider.AndroidViewModelFactory getInstance(android.app.Application application);
}

public static interface ViewModelProvider.Factory {
method public <T extends androidx.lifecycle.ViewModel> T create(Class<T!>);
method public <T extends androidx.lifecycle.ViewModel> T create(Class<T> modelClass);
}

public static class ViewModelProvider.NewInstanceFactory implements androidx.lifecycle.ViewModelProvider.Factory {
ctor public ViewModelProvider.NewInstanceFactory();
method public <T extends androidx.lifecycle.ViewModel> T create(Class<T!>);
method public <T extends androidx.lifecycle.ViewModel> T create(Class<T> modelClass);
field public static final androidx.lifecycle.ViewModelProvider.NewInstanceFactory.Companion Companion;
}

public static final class ViewModelProvider.NewInstanceFactory.Companion {
}

public class ViewModelStore {
Expand Down
39 changes: 30 additions & 9 deletions lifecycle/lifecycle-viewmodel/api/restricted_current.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,25 +16,46 @@ package androidx.lifecycle {
}

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!>);
method @MainThread public <T extends androidx.lifecycle.ViewModel> T get(String, Class<T!>);
ctor public ViewModelProvider(androidx.lifecycle.ViewModelStore store, androidx.lifecycle.ViewModelProvider.Factory factory);
ctor public ViewModelProvider(androidx.lifecycle.ViewModelStoreOwner owner);
ctor public ViewModelProvider(androidx.lifecycle.ViewModelStoreOwner owner, androidx.lifecycle.ViewModelProvider.Factory factory);
method @MainThread public operator <T extends androidx.lifecycle.ViewModel> T get(Class<T> modelClass);
method @MainThread public operator <T extends androidx.lifecycle.ViewModel> T get(String key, Class<T> modelClass);
}

public static class ViewModelProvider.AndroidViewModelFactory extends androidx.lifecycle.ViewModelProvider.NewInstanceFactory {
ctor public ViewModelProvider.AndroidViewModelFactory(android.app.Application);
method public static androidx.lifecycle.ViewModelProvider.AndroidViewModelFactory getInstance(android.app.Application);
ctor public ViewModelProvider.AndroidViewModelFactory(android.app.Application application);
method public static final androidx.lifecycle.ViewModelProvider.AndroidViewModelFactory getInstance(android.app.Application application);
field public static final androidx.lifecycle.ViewModelProvider.AndroidViewModelFactory.Companion Companion;
}

public static final class ViewModelProvider.AndroidViewModelFactory.Companion {
method public androidx.lifecycle.ViewModelProvider.AndroidViewModelFactory getInstance(android.app.Application application);
}

public static interface ViewModelProvider.Factory {
method public <T extends androidx.lifecycle.ViewModel> T create(Class<T!>);
method public <T extends androidx.lifecycle.ViewModel> T create(Class<T> modelClass);
}

@RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP) public abstract static class ViewModelProvider.KeyedFactory extends androidx.lifecycle.ViewModelProvider.OnRequeryFactory implements androidx.lifecycle.ViewModelProvider.Factory {
method public abstract <T extends androidx.lifecycle.ViewModel> T create(String key, Class<T> modelClass);
method public <T extends androidx.lifecycle.ViewModel> T create(Class<T> modelClass);
}

public static class ViewModelProvider.NewInstanceFactory implements androidx.lifecycle.ViewModelProvider.Factory {
ctor public ViewModelProvider.NewInstanceFactory();
method public <T extends androidx.lifecycle.ViewModel> T create(Class<T!>);
method public <T extends androidx.lifecycle.ViewModel> T create(Class<T> modelClass);
method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP) public static final androidx.lifecycle.ViewModelProvider.NewInstanceFactory getInstance();
field public static final androidx.lifecycle.ViewModelProvider.NewInstanceFactory.Companion Companion;
}

public static final class ViewModelProvider.NewInstanceFactory.Companion {
method @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP) public androidx.lifecycle.ViewModelProvider.NewInstanceFactory getInstance();
property @RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP) public final androidx.lifecycle.ViewModelProvider.NewInstanceFactory instance;
}

@RestrictTo(androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP) public static class ViewModelProvider.OnRequeryFactory {
method public void onRequery(androidx.lifecycle.ViewModel viewModel);
}

public class ViewModelStore {
Expand Down
2 changes: 1 addition & 1 deletion lifecycle/lifecycle-viewmodel/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ android {

dependencies {
api("androidx.annotation:annotation:1.1.0")

api(libs.kotlinStdlib)
testImplementation(libs.junit)
testImplementation(libs.mockitoCore)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,14 @@

/**
* Interface that marks a {@link ViewModelStoreOwner} as having a default
* {@link ViewModelProvider.Factory} for use with
* {@link ViewModelProvider#ViewModelProvider(ViewModelStoreOwner)}.
* {@link androidx.lifecycle.ViewModelProvider.Factory} for use with
* {@link androidx.lifecycle.ViewModelProvider#ViewModelProvider(ViewModelStoreOwner)}.
*/
public interface HasDefaultViewModelProviderFactory {
/**
* Returns the default {@link ViewModelProvider.Factory} that should be
* Returns the default {@link androidx.lifecycle.ViewModelProvider.Factory} that should be
* used when no custom {@code Factory} is provided to the
* {@link ViewModelProvider} constructors.
* {@link androidx.lifecycle.ViewModelProvider} constructors.
*
* @return a {@code ViewModelProvider.Factory}
*/
Expand Down
Loading

0 comments on commit 927300f

Please sign in to comment.