百度反推源码(校招内推码怎么获得)

   抖音SEO    

使用协程,相信很多同学已经信手拈来了,但是关于ViewModelScope,可能很多同学在用,但却不知道原理,今天来一探究竟。


ViewModelScope,顾名思义,在ViewModel中使用的协程。它是ViewModel的扩展属性。


推荐理由:



后面会重点介绍ViewModelScope是怎么做到不会内存泄漏的。





ViewModelScope虽然是协程,但属于androidx.lifecycle包中ViewModel的扩展属性。


使用非常简单,关键在于它是怎么保证不会内存泄露的?

来看viewModelScope源码:



先看get()方法:



return中通过setTagIfAbsent创建了协程,并且指定主线程。


先忽略setTagIfAbsent,来看协程创建的方式:



CloseableCoroutineScope,顾名思义,可以关闭的协程。


实现Closeable接口,并重写唯一方法close(),并在方法中取消了协程。


现在我们已经知道了viewModelScope是可以取消的了,关键就在于取消时机的控制了。


回过头在再看setTagIfAbsent,setTagIfAbsent是ViewModel中的方法



在setTagIfAbsent中,以HashMap的形式把协程对象保存起来了,并配有getTag方法。


可能有同学已经注意到最后的方法closeWithRuntimeException,因为这个方法中调用了Closeable接口的close()方法,而close()方法就是用来取消协程的。


而closeWithRuntimeException方法是谁调用的呢,主要是ViewModel中的clear()方法。



这里是循环保存协程的HashMap,然后调用closeWithRuntimeException取消协程。


那这个ViewModel中的clear()方法又是谁调用的呢?


查看源码,只有一处调用,就是在ViewModelStore中



ViewModelStore的源码比较少,也很简单。


同样也是以HashMap的形式来保存ViewModel。


那是什么时候保存的呢,我们来追踪一下put方法:



在ViewModelProvider的get方法中调用了put,也就是说,我们在创建ViewModel的时候并把其保存了起来。


回过头来再看ViewModelStore,同样也有一个clear()方法,同样循环调用vm.clear()。


继续追踪ViewModelStore的clear()方法是在哪调用的。


是在ComponentActivity.java中调用的:



先是获取Lifecycle,并添加生命周期监听。


在生命周期为onDestroy的时候,获取ViewModelStore,并调用其clear()方法。


至此,相信大部分同学都明白了ViewModelScope为什么不会造成内存泄露了,因为在onDestroy的时候会取消执行,只不过这部分工作源码已经替我们完成了。


关于怎么获取到当前生命周期状态的,就涉及到Lifecycle相关的知识了,简而言之,不管是Activity还是Fragment,都是LifecycleOwner,其实是父类实现的,比如ComponentActivity。在父类中通过ReportFragment或ActivityLifecycleCallbacks接口来派发当前生命周期状态,具体使用哪种派发方式要看Api等级是否在29(10.0)及以上,及 则后者。


author:yechaoa

最后,我们再来总结一下ViewModelScope的整个流程。



为避免有的同学没理解,我们再反推梳理一次



ok,以上就是ViewModelScope的使用,以及源码分析。

写作不易,如果对你有一丢丢帮助或启发,感谢点赞支持 ^ - ^

 标签:

评论留言

我要留言

欢迎参与讨论,请在这里发表您的看法、交流您的观点。