当前位置: 首页 > news >正文

良品铺子vi设计手册百度seo优化教程免费

良品铺子vi设计手册,百度seo优化教程免费,如何制作个人网页文档,承德网站开发区地税Android Jetpack组件架构:ViewModel的原理 导言 本篇文章是关于介绍ViewModel的,由于ViewModel的使用还是挺简单的,这里就不再介绍其的基本应用,我们主要来分析ViewModel的原理。 ViewModel的生命周期 众所周知,一般…

Android Jetpack组件架构:ViewModel的原理

在这里插入图片描述

导言

本篇文章是关于介绍ViewModel的,由于ViewModel的使用还是挺简单的,这里就不再介绍其的基本应用,我们主要来分析ViewModel的原理。

ViewModel的生命周期

众所周知,一般使用ViewModel是用来解决两个问题的,第一个就是关于设备配置发生改变时Activity先前状态的保存,在ViewModel出来之前我们一般会使用saveInstanceState这个Bundle来进行状态的保存,但是这样做能存储的数据是有限的,结构也不够明确,ViewModel作为一个生命周期大于Activity的组件就可以帮我们实现状态的存储,下面是ViewModel生命周期与Activity对比的图:
在这里插入图片描述
可以看到直到Activity被完全Destory时ViewModel中的数据才会被清除。

我们使用ViewModel的第二个原因就是用来实现MVVM架构,可以通过DataBinding组件和ViewModel组件以及LiveData组件一起实现MVVM架构,这样可以减轻Activity的职责,避免Activity过于臃肿。

获得ViewModel的提供者

我们从ViewModel的创建开始分析其原理,这里用我们上一篇文章的例子:

mViewModel = ViewModelProvider(this).get(SimpViewModel::class.java)

这里首先会通过ViewModelProvider的构造方法获得一个ViewModelProvider的实例,其构造方法如下所示:

public constructor(owner: ViewModelStoreOwner
) : this(owner.viewModelStore, defaultFactory(owner), defaultCreationExtras(owner))constructor(private val store: ViewModelStore,private val factory: Factory,private val defaultCreationExtras: CreationExtras = CreationExtras.Empty,
)

可以看到我们调用的是第一个构造方法,最终会调用到第二个构造方法中,也就是主构造方法中,这个构造来说就是指定了三个成员变量,分别是ViewModelStore,FactoryCreationExtras三个类型的参数,我们先来分别介绍一下这三个类型。

ViewModelStore – ViewModel的拥有者

着整个类比较小,但是也是有注释的,我们先来看看注释:
在这里插入图片描述
这段注释中比较重要的信息就是ViewModel是真正用来存储ViewModel的类并且在configuration changes就是配置发生改变时新的实例和旧的实例中的信息是一致的。只有当持有者不再会被recreated时里面的数据才会通过clear清除。

接下来我们来看该类的源码:

public class ViewModelStore {private final HashMap<String, ViewModel> mMap = new HashMap<>();final void put(String key, ViewModel viewModel) {ViewModel oldViewModel = mMap.put(key, viewModel);if (oldViewModel != null) {oldViewModel.onCleared();}}final ViewModel get(String key) {return mMap.get(key);}Set<String> keys() {return new HashSet<>(mMap.keySet());}public final void clear() {for (ViewModel vm : mMap.values()) {vm.clear();}mMap.clear();}
}

可以看到具体是用一个哈希表来存储viewModel的实例的,里面唯一比较大的方法就是put方法,里面做的处理就是将替换出来的旧的viewModel实例给清理掉。

Factory – ViewModel的创建工厂

这个Factory是一个定义在ViewModelProvider的内部接口,它的主要职责是用来初始化ViewModel,说实话就是一个工厂。我们来看其定义:

    public interface Factory {public fun <T : ViewModel> create(modelClass: Class<T>): T {throw UnsupportedOperationException("Factory.create(String) is unsupported.  This Factory requires " +"`CreationExtras` to be passed into `create` method.")}public fun <T : ViewModel> create(modelClass: Class<T>, extras: CreationExtras): T =create(modelClass)companion object {@JvmStaticfun from(vararg initializers: ViewModelInitializer<*>): Factory =InitializerViewModelFactory(*initializers)}}

不过这里是一个抽象的,我们来找一个具体的,也就是defaultFactory方法获取的工厂:

public companion object {internal fun defaultFactory(owner: ViewModelStoreOwner): Factory =if (owner is HasDefaultViewModelProviderFactory)owner.defaultViewModelProviderFactory else instance......       
}

这个方法的逻辑就是判断ViewModel的持有者是不是有默认的工厂方法,如果有的话就获取持有者的默认工厂,否则返回的是自身的instance实例,至于这个instance实例是在NewInstanceFactory这个实现了Factory接口的工厂类中定义的伴生变量,具体逻辑是:

@JvmStatic
public val instance: NewInstanceFactory@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)get() {if (sInstance == null) {sInstance = NewInstanceFactory()}return sInstance!!}

可以看到instance是一个静态的单例,他具体指向的还是这个NewInstanceFactory类,至于它是如何初始化/创建ViewModel的实例的我们可以看一眼它的create方法:

override fun <T : ViewModel> create(modelClass: Class<T>): T {return try {modelClass.newInstance()} catch (e: InstantiationException) {throw RuntimeException("Cannot create an instance of $modelClass", e)} catch (e: IllegalAccessException) {throw RuntimeException("Cannot create an instance of $modelClass", e)}
}

这个传入的modelClass就是我们传入的.class文件:

ViewModelProvider(this).get(SimpViewModel::class.java)

所以可以看到,这个默认情况下的工厂就是直接用反射生成了对应ViewModel的实例。

CreationExtras – 构建ViewModel时的额外参数

首先我们来看一看注释的内容:
在这里插入图片描述
简单来说它就是为工厂生成实例的时候提供额外参数的,这些参数使用一个Map来存储的了,不过默认情况下我们并不需要实现额外的工厂,所以这个类型我们先略过。

获得ViewModel的实例

前面我们已经知道了通过构造ViewModelProvider我们可以获得其Factory了,接下来继续向下看:

ViewModelProvider(this).get(SimpViewModel::class.java)

我们看一看get方法做了什么:

    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)}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] = keyreturn try {factory.create(modelClass, extras)} catch (e: AbstractMethodError) {factory.create(modelClass)}.also { store.put(key, it) }}

可以看到第一个方法会调用第二个方法,其中第一个方法向第二个方法传入的的第一个String类型的参数是通过DEFAULT_KEY和我们传入的类的类名拼接而成的。然后跳转到第二个方法之中去,首先会尝试从ViewModleStroe中获取对应Key对应的ViewModel,但是一般第一次创建时应该会为null,所以之后跳转的应该是最后return块中的factory.create方法之中,这个方法我们在之前Factory的介绍中提到过了,具体就是通过反射实例化ViewModel的,并且最后将其放入到ViewModelStore对象之中去。

至于多次获取同一个ViewModel实例是会跳转到:

 if (modelClass.isInstance(viewModel)) {(factory as? OnRequeryFactory)?.onRequery(viewModel)return viewModel as T} 

这一段中去,这里onRequery默认是无实现的,也就是说并不会对viewModel做任何的处理。

ViewModelStore在哪里被创建

既然ViewModel是被存储在ViewModelStore之中的,那ViewModelStore究竟是在哪里被创建出来的呢?我们可以在ComponentActivity之中找到答案:

public ViewModelStore getViewModelStore() {if (getApplication() == null) {throw new IllegalStateException("Your activity is not yet attached to the "+ "Application instance. You can't request ViewModel before onCreate call.");}ensureViewModelStore();return mViewModelStore;
}void ensureViewModelStore() {if (mViewModelStore == null) {NonConfigurationInstances nc =(NonConfigurationInstances) getLastNonConfigurationInstance(); //获得上次配置更改的相关参数if (nc != null) { //当存在上次的参数时// Restore the ViewModelStore from NonConfigurationInstancesmViewModelStore = nc.viewModelStore; //恢复上次的参数}if (mViewModelStore == null) {mViewModelStore = new ViewModelStore(); //创建一个新的ViewModelStore}}
}

可以看到这里在获得ViewModelStore时主要是通过一个NonConfigurationInstances ,而该参数是一个静态的对象,也就是说,它是一个单例,这样就保证了Activity在整个生命周期之中只有一个ViewModelStore实例,从而实现配置改变时也可以恢复数据的作用。

Activity的默认工厂

在看ComponentActivity的源码时,发现了原来Activity也是有默认工厂的,它的具体实现如下:

    constructor(application: Application?, owner: SavedStateRegistryOwner, defaultArgs: Bundle?) {savedStateRegistry = owner.savedStateRegistrylifecycle = owner.lifecyclethis.defaultArgs = defaultArgsthis.application = applicationfactory = if (application != null) getInstance(application)else ViewModelProvider.AndroidViewModelFactory()}

这个方法最终设置到的工厂类都是一个名为AndroidViewModelFactory的工厂类:

    public open class AndroidViewModelFactoryprivate constructor(private val application: Application?,// parameter to avoid clash between constructors with nullable and non-nullable// Application@Suppress("UNUSED_PARAMETER") unused: Int,) : NewInstanceFactory() {@Suppress("SingletonConstructor")public constructor() : this(null, 0)@Suppress("SingletonConstructor")public constructor(application: Application) : this(application, 0)@Suppress("DocumentExceptions")override fun <T : ViewModel> create(modelClass: Class<T>, extras: CreationExtras): T {return if (application != null) {create(modelClass)} else {val application = extras[APPLICATION_KEY]if (application != null) {create(modelClass, application)} else {// For AndroidViewModels, CreationExtras must have an application setif (AndroidViewModel::class.java.isAssignableFrom(modelClass)) {throw IllegalArgumentException("CreationExtras must have an application by `APPLICATION_KEY`")}super.create(modelClass)}}}@Suppress("DocumentExceptions")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)) {//如果传入的Class类型实现的接口和AndroidViewModel::class一致,及说明也有生命周期,调用构造犯法并且传入application对象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 instanceinternal const val DEFAULT_KEY = "androidx.lifecycle.ViewModelProvider.DefaultKey"private var sInstance: AndroidViewModelFactory? = null@JvmStaticpublic fun getInstance(application: Application): AndroidViewModelFactory {if (sInstance == null) {sInstance = AndroidViewModelFactory(application)}return sInstance!!}private object ApplicationKeyImpl : Key<Application>@JvmFieldval APPLICATION_KEY: Key<Application> = ApplicationKeyImpl}}

具体通过getInstance方法就跳转到了这里,可以发现似乎工厂类都是一个单例的模式,这个工厂的特殊之处就是他的create方法涉及到了Application对象的传入,比如说这里的newInstance方法:

modelClass.getConstructor(Application::class.java).newInstance(app)public T newInstance(Object ... initargs)throws InstantiationException, IllegalAccessException,IllegalArgumentException, InvocationTargetException
{if (serializationClass == null) {return newInstance0(initargs);} else {return (T) newInstanceFromSerialization(serializationCtor, serializationClass);}
}

也就是说整个被传入Application的生命周期内都只有一个实例,这样由于创建的实例在生命周期范围内的单例性和ViewModelStore的单例性,整个ViewModel就可以实现在整个Activity的生命周期内(发生意外,比如说配置改变时)数据不变更的作用。

http://www.zhongyajixie.com/news/36161.html

相关文章:

  • 把做的网站放到互联网上梁水才seo优化专家
  • 做网站日入100站内关键词排名优化软件
  • 我自己做的网站怎么能查到网络推广哪个平台最好
  • 企业建网站需要准备哪些资料呢域名注册管理机构
  • 酒店网站建设的重要性网上接单平台
  • 网站测试软件app推广赚钱
  • 手机网站制作教程下载发布软文的平台有哪些
  • 商务网站建设摘要常用的seo工具推荐
  • 那个视频网站做公开课比较好网络搜索优化
  • 密云区免费网站建设中国网络营销公司
  • 做卖号网站吗四川疫情最新消息
  • 加快建设公司新版网站电商的运营模式有几种
  • html5安卓软件下载爱站seo工具包下载
  • 丰顺网站建设抖音代运营收费详细价格
  • 四川整站优化专业的机构百度关键词热度
  • 旅游网站设计与实现开题报告知名做网站的公司
  • 米拓做网站图片在哪里删掉网页开发需要学什么
  • 做网站最省钱宁波seo营销平台
  • 北京海淀网站建设seo内容优化是什么意思
  • 安徽省住房和城乡建设厅网站查询上海网络推广服务公司
  • 现在建设的网站有什么劣势排行榜前十名
  • 效果图网站排行百度天眼查
  • 给窗帘做网站怎么做网站推广多少钱
  • 游戏中心官网sem和seo是什么
  • 网站建设找哪家免费浏览外国网站的软件
  • 郑州做网站茂睿科技百度推广怎么优化排名
  • 图片定制软件百度关键词优化送网站
  • 深圳网站设计价格表即时热榜
  • 做网站卖装备网络广告人社区官网
  • 企业网站的总体设计推荐seo关键词优化