// 调用上一个构造方法只是准备了一些参数然后调用此构造,可见此时ViewModelProvider中有一个关键变量:store、factory、defaultCreationExtras constructor( private val store: ViewModelStore, private val factory: Factory, private val defaultCreationExtras: CreationExtras = CreationExtras.Empty, ) { ... public open class AndroidViewModelFactory private constructor( private val application: Application?, @Suppress("UNUSED_PARAMETER") unused: Int, ) : NewInstanceFactory() {
public constructor() : this(null, 0)
public constructor(application: Application) : this(application, 0)
override fun <T : ViewModel> create(modelClass: Class<T>, extras: CreationExtras): T { return if (application != null) { create(modelClass, application) } else { val application = extras[APPLICATION_KEY] if (application != null) { create(modelClass, application) } else { if (AndroidViewModel::class.java.isAssignableFrom(modelClass)) { throw IllegalArgumentException( "CreationExtras must have an application by `APPLICATION_KEY`" ) } super.create(modelClass) } } }
override fun <T : ViewModel> create(modelClass: Class<T>): T { return if (application == null) { throw UnsupportedOperationException( "AndroidViewModelFactory constructed " + "with empty constructor works only with " + "create(modelClass: Class<T>, extras: CreationExtras)." ) } else { create(modelClass, application) } }
@Suppress("DocumentExceptions") private fun <T : ViewModel> create(modelClass: Class<T>, app: Application): T { return if (AndroidViewModel::class.java.isAssignableFrom(modelClass)) { try { modelClass.getConstructor(Application::class.java).newInstance(app) } catch (e: NoSuchMethodException) { throw RuntimeException("Cannot create an instance of $modelClass", e) } catch (e: IllegalAccessException) { throw RuntimeException("Cannot create an instance of $modelClass", e) } catch (e: InstantiationException) { throw RuntimeException("Cannot create an instance of $modelClass", e) } catch (e: InvocationTargetException) { throw RuntimeException("Cannot create an instance of $modelClass", e) } } else super.create(modelClass) }
public companion object { internal fun defaultFactory(owner: ViewModelStoreOwner): Factory = if (owner is HasDefaultViewModelProviderFactory) owner.defaultViewModelProviderFactory else instance
internal const val DEFAULT_KEY = "androidx.lifecycle.ViewModelProvider.DefaultKey"
private var sInstance: AndroidViewModelFactory? = null @JvmStatic public fun getInstance(application: Application): AndroidViewModelFactory { if (sInstance == null) { sInstance = AndroidViewModelFactory(application) } return sInstance!! }
@MainThread public open operator fun <T : ViewModel> get(modelClass: Class<T>): T { val canonicalName = modelClass.canonicalName ?: throw IllegalArgumentException("Local and anonymous classes can not be ViewModels") return get("$DEFAULT_KEY:$canonicalName", modelClass) }
@MainThread public open operator fun <T : ViewModel> get(key: String, modelClass: Class<T>): T { // 先尝试从ViewModelStore中获取需要的ViewModel实例 val viewModel = store[key] if (modelClass.isInstance(viewModel)) { (factory as? OnRequeryFactory)?.onRequery(viewModel) // 如果实例存在直接返回,如果不存在走下面逻辑通过Factory去创建 return viewModel as T } else { @Suppress("ControlFlowWithEmptyBody") if (viewModel != null) { // TODO: log a warning. } } val extras = MutableCreationExtras(defaultCreationExtras) extras[VIEW_MODEL_KEY] = key // ViewModel是第一次创建的话则通过ViewModelProvider.Factory去创建一个新的ViewModel并返回,返回之前也会把它加入ViewModelStore中进行缓存,下一次如果再需要获取同类型的ViewModel时就无需再创建并且数据也能得以保留 return try { factory.create(modelClass, extras) } catch (e: AbstractMethodError) { factory.create(modelClass) }.also { store.put(key, it) } }
final class FragmentManagerViewModel extends ViewModel { ... void clearNonConfigState(@NonNull Fragment f) { if (FragmentManager.isLoggingEnabled(Log.DEBUG)) { Log.d(TAG, "Clearing non-config state for " + f); } // Clear and remove the Fragment's child non config state FragmentManagerViewModel childNonConfig = mChildNonConfigs.get(f.mWho); if (childNonConfig != null) { childNonConfig.onCleared(); mChildNonConfigs.remove(f.mWho); } // Clear and remove the Fragment's ViewModelStore ViewModelStore viewModelStore = mViewModelStores.get(f.mWho); if (viewModelStore != null) { viewModelStore.clear(); mViewModelStores.remove(f.mWho); } } ... }