1 /*
<lambda>null2  * Copyright 2024 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package androidx.lifecycle.viewmodel
18 
19 import androidx.lifecycle.ViewModel
20 import androidx.lifecycle.ViewModelProvider
21 import androidx.lifecycle.ViewModelStore
22 import androidx.lifecycle.viewmodel.internal.SynchronizedObject
23 import androidx.lifecycle.viewmodel.internal.ViewModelProviders
24 import androidx.lifecycle.viewmodel.internal.synchronized
25 import kotlin.reflect.KClass
26 
27 /**
28  * Internal implementation of the multiplatform [ViewModelProvider].
29  *
30  * Kotlin Multiplatform does not support expect class with default implementation yet, so we
31  * extracted the common logic used by all platforms to this internal class.
32  *
33  * @see <a href="https://youtrack.jetbrains.com/issue/KT-20427">KT-20427</a>
34  */
35 internal class ViewModelProviderImpl(
36     private val store: ViewModelStore,
37     private val factory: ViewModelProvider.Factory,
38     private val defaultExtras: CreationExtras,
39 ) {
40 
41     private val lock = SynchronizedObject()
42 
43     @Suppress("UNCHECKED_CAST")
44     internal fun <T : ViewModel> getViewModel(
45         modelClass: KClass<T>,
46         key: String = ViewModelProviders.getDefaultKey(modelClass),
47     ): T {
48         return synchronized(lock) {
49             val viewModel = store[key]
50             if (modelClass.isInstance(viewModel)) {
51                 if (factory is ViewModelProvider.OnRequeryFactory) {
52                     factory.onRequery(viewModel!!)
53                 }
54                 return@synchronized viewModel as T
55             }
56 
57             val modelExtras = MutableCreationExtras(defaultExtras)
58             modelExtras[ViewModelProvider.VIEW_MODEL_KEY] = key
59 
60             return@synchronized createViewModel(factory, modelClass, modelExtras).also { vm ->
61                 store.put(key, vm)
62             }
63         }
64     }
65 }
66 
67 /**
68  * Returns a new instance of a [ViewModel].
69  *
70  * **Important:** Android targets using `compileOnly` dependencies may encounter AGP desugaring
71  * issues where `Factory.create` throws an `AbstractMethodError`. This is resolved by an
72  * Android-specific implementation that first attempts all `ViewModelProvider.Factory.create` method
73  * overloads before allowing the exception to propagate.
74  *
75  * @see <a href="https://b.corp.google.com/issues/230454566">b/230454566</a>
76  * @see <a href="https://b.corp.google.com/issues/341792251">b/341792251</a>
77  * @see <a href="https://github.com/square/leakcanary/issues/2314">leakcanary/issues/2314</a>
78  * @see <a href="https://github.com/square/leakcanary/issues/2677">leakcanary/issues/2677</a>
79  */
createViewModelnull80 internal expect fun <VM : ViewModel> createViewModel(
81     factory: ViewModelProvider.Factory,
82     modelClass: KClass<VM>,
83     extras: CreationExtras,
84 ): VM
85