ViewModel源码阅读笔记

MVVM模式实现了数据和页面的分离。ViewModel的生命周期需要跟随引用他的activity或者fragment。接下来我们就来看看,ViewModel是如何实现生命周期的伴随的。

先从ViewModel的创建开始看

XXXViewModel viewModel = new  ViewModelProvider(fragment).get(XXXViewModel.class)

kotlin扩展函数实现的方式最终也是调用ViewModelProvider的方法实现的,具体细节可以看上篇文章介绍,这里不赘述了

先看下ViewModelProvider的构造方法

public ViewModelProvider(@NonNull ViewModelStoreOwner owner) {  
this(owner.getViewModelStore(), owner instanceof HasDefaultViewModelProviderFactory  
        ? ((HasDefaultViewModelProviderFactory) owner).getDefaultViewModelProviderFactory()  
        : NewInstanceFactory.getInstance());  
}

构造方法需要传入一个ViewModelStoreOwner,在androidx包中的Fragment和ComponentActivity都实现了这个接口。这个稍后再看

继续看上面的代码,该构造方法调用了另一个构造方法

public ViewModelProvider(@NonNull ViewModelStore store, @NonNull Factory factory) {  
    mFactory = factory;  
    mViewModelStore = store;  
}

mViewModelStore这个变量来自于ViewModelStoreOwner,接下来以Fragment为例,来看看

public ViewModelStore getViewModelStore() {  
    if (mFragmentManager == null) {  
        throw new IllegalStateException("Can't access ViewModels from detached fragment");  
    }  
    return mFragmentManager.getViewModelStore(this);  
}

这里可以看出,Fragment的ViewModelStore是保存在当前实例下。先记住这个结论,待会还用得着。

接下来看factory参数,fragment也是HasDefaultViewModelProviderFactory的实现类,因此获取factory的实例方法为

public ViewModelProvider.Factory getDefaultViewModelProviderFactory() {  
    if (mFragmentManager == null) {  
        throw new IllegalStateException("Can't access ViewModels from detached fragment");  
    }  
    if (mDefaultFactory == null) {  
        mDefaultFactory = new SavedStateViewModelFactory(  
            requireActivity().getApplication(),  
            this,  
            getArguments());  
    }  
    return mDefaultFactory;  
}

这里的factory也是fragment中保存的实例

回到ViewModelProvider的get方法

public <T extends ViewModel> T get(@NonNull Class<T> modelClass) {  
    String canonicalName = modelClass.getCanonicalName();  
    if (canonicalName == null) {  
        throw new IllegalArgumentException("Local and anonymous classes can not be ViewModels");  
    }  
    return get(DEFAULT_KEY + ":" + canonicalName, modelClass);  
}

最终调用的是

public <T extends ViewModel> T get(@NonNull String key, @NonNull Class<T> modelClass) {  
    ViewModel viewModel = mViewModelStore.get(key);
    if (modelClass.isInstance(viewModel)) {  
        if (mFactory instanceof OnRequeryFactory) {  
            ((OnRequeryFactory) mFactory).onRequery(viewModel);  
        }  
        return (T) viewModel;  
    } else {  
        //noinspection StatementWithEmptyBody  
        if (viewModel != null) {  
            // TODO: log a warning.  
        }  
    }  
    if (mFactory instanceof KeyedFactory) {  
        viewModel = ((KeyedFactory) (mFactory)).create(key, modelClass);  
    } else {  
        viewModel = (mFactory).create(modelClass);  
    }  
    mViewModelStore.put(key, viewModel);  
    return (T) viewModel;  
}

这里获取缓存的viewmodel的方法 mViewModelStore.get(key)。这里的mViewModelStore就是fragment中存储的。

讲到这里,其实已经清楚了生命周期的绑定过成了。

在ViewModelProvider获取ViewModel的时候,实际上是从fragment中拿到的,如果fragment中没有的话,就创建一个,将其保存在fragment中。因此,只要拿到的fragment实例为同一个,无论新创建多少个ViewModelProvider的实例,最终获取的ViewModel都是同一个。而因为ViewModel的实例实际上是保存在fragment中,因此,viewmodel也会随fragment的销毁而销毁。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容