自学内容网 自学内容网

viewmodel创建及使用分析

1、相关的类

  • ViewModelStore :管理viewModel实例,内部包含一个Map用来存储viewmodel,内部包括put、get、clear等方法
  • ViewModelProvider :管理ViewModelStore和Factory,Factory里面有create方法是创建对应的viewmodel的,ViewModelProvider内部有一个get方法获取viewmodel

2、在项目中应用

首先新建项目分别创建TestViewModel
TestViewModel.class

fun provideFactory(
            repository: TestRepository
        ): ViewModelProvider.Factory = object : ViewModelProvider.Factory {
            @Suppress("UNCHECKED_CAST")
            override fun <T : ViewModel> create(modelClass: Class<T>): T {
                return TestViewModel(repository) as T
            }
        }

MainActivity.class中初始化代码:

    private val testViewModel by viewModels<TestViewModel> {
        TestViewModel.provideFactory(TestRepository())
    }

接下来在MainActivity里面就可以正常使用这个viewmodel了

3、流程简单解析

首先我们在mainActivity里面初始化时候使用了by viewmodel 这个方式进行初始化点击进入这个方法之后源码如下:

public inline fun <reified VM : ViewModel> ComponentActivity.viewModels(
    noinline extrasProducer: (() -> CreationExtras)? = null,
    noinline factoryProducer: (() -> Factory)? = null
): Lazy<VM> {
    val factoryPromise = factoryProducer ?: {
        defaultViewModelProviderFactory
    }

    return ViewModelLazy(
        VM::class,
        { viewModelStore },
        factoryPromise,
        { extrasProducer?.invoke() ?: this.defaultViewModelCreationExtras }
    )
}

可以看到viewModels是ComponentActivity的一个扩展函数,参数需要传factoryProducer,factoryProducer就是前面我们提到过的ViewModelProvider的内部的一个factory类,用来创建viewModel的,所以我们传入TestViewModel.provideFactory。
继续向下看进入ViewModelLazy:

public class ViewModelLazy<VM : ViewModel> @JvmOverloads constructor(
    private val viewModelClass: KClass<VM>,
    private val storeProducer: () -> ViewModelStore,
    private val factoryProducer: () -> ViewModelProvider.Factory,
    private val extrasProducer: () -> CreationExtras = { CreationExtras.Empty }
) : Lazy<VM> {
    private var cached: VM? = null

    override val value: VM
        get() {
            val viewModel = cached
            return if (viewModel == null) {
                val factory = factoryProducer()
                val store = storeProducer()
                ViewModelProvider(
                    store,
                    factory,
                    extrasProducer()
                ).get(viewModelClass.java).also {
                    cached = it
                }
            } else {
                viewModel
            }
        }

    override fun isInitialized(): Boolean = cached != null
}

首先判断是否有缓存,如果有缓存直接返回,无缓存情况下就去ViewModelProvider获取对应的viewmodel并且进行一下缓存操作,接下来我们看一下ViewModelProvider的get方法

    public open operator fun <T : ViewModel> get(key: String, modelClass: Class<T>): T {
        val viewModel = store[key]
        if (modelClass.isInstance(viewModel)) {
            (factory as? OnRequeryFactory)?.onRequery(viewModel!!)
            return viewModel as T
        } else {
            @Suppress("ControlFlowWithEmptyBody")
            if (viewModel != null) {
                // TODO: log a warning.
            }
        }
        val extras = MutableCreationExtras(defaultCreationExtras)
        extras[VIEW_MODEL_KEY] = key
        // AGP has some desugaring issues associated with compileOnly dependencies so we need to
        // fall back to the other create method to keep from crashing.
        return try {
            factory.create(modelClass, extras)
        } catch (e: AbstractMethodError) {
            factory.create(modelClass)
        }.also { store.put(key, it) }
    }

get方法通过内部的store传入类名来获取view model,那么store是从哪里来的呢?往回看能看到是在ComponentActivity.viewModels这里返回了一个ViewModelLazy时传入了viewModelStore,这个viewModelStore是从ComponentActivity初始化时候就创建了的

    public ComponentActivity() {
        //......
        getLifecycle().addObserver(new LifecycleEventObserver() {
            @Override
            public void onStateChanged(@NonNull LifecycleOwner source,
                    @NonNull Lifecycle.Event event) {
                if (event == Lifecycle.Event.ON_DESTROY) {
                    // Clear out the available context
                    mContextAwareHelper.clearAvailableContext();
                    // And clear the ViewModelStore
                    if (!isChangingConfigurations()) {
                        getViewModelStore().clear();
                    }
                    mReportFullyDrawnExecutor.activityDestroyed();
                }
            }
        });
        getLifecycle().addObserver(new LifecycleEventObserver() {
            @Override
            public void onStateChanged(@NonNull LifecycleOwner source,
                    @NonNull Lifecycle.Event event) {
                ensureViewModelStore();
                getLifecycle().removeObserver(this);
            }
        });
        //......
    }
        void ensureViewModelStore() {
        if (mViewModelStore == null) {
            NonConfigurationInstances nc =
                    (NonConfigurationInstances) getLastNonConfigurationInstance();
            if (nc != null) {
                // Restore the ViewModelStore from NonConfigurationInstances
                mViewModelStore = nc.viewModelStore;
            }
            if (mViewModelStore == null) {
                mViewModelStore = new ViewModelStore();
            }
        }
    }

在activity创建时添加生命周期监听,生命周期变更时创建ViewModelStore,当生命周期destory时会通过isChangingConfigurations来判断是否是通过切换横竖屏导致的destroy,如果是的话不会对view model执行clear,这样保证了view model在切换横竖屏时依然可以保存数据,等页面真正的退出执行的destroy时才会对viewmodel执行clear方法,这样保证了viewmodel的生命周期和activity一致,也不需要我们单独对其生命周期进行维护。

针对这个流程简单的分析,如有分析不符的地方欢迎评论指正


原文地址:https://blog.csdn.net/qq_41167962/article/details/140315714

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!