Android ViewModel详解
轉(zhuǎn)載請(qǐng)標(biāo)明出處:http://blog.csdn.net/zhaoyanjun6/article/details/119828016
本文出自【趙彥軍的博客】
文章目錄
- ViewModel簡(jiǎn)介
- ViewModel生命周期
- ViewModel 使用
- Fragment使用
- ktx 擴(kuò)展
- activity 擴(kuò)展
- fragment 擴(kuò)展
- AndroidViewModel
ViewModel簡(jiǎn)介
視圖與數(shù)據(jù)模型之間的橋梁ViewModel
ViewModel生命周期
ViewModel的生命周期會(huì)比創(chuàng)建它的Activity、Fragment的生命周期都要長(zhǎng)。即ViewModel中的數(shù)據(jù)會(huì)一直存活在Activity/Fragment中。
眾所周知,由于Android平臺(tái)的特殊性,若應(yīng)用程序發(fā)送屏幕旋轉(zhuǎn)的時(shí)候會(huì)經(jīng)歷Activity的銷毀與重建,這里就涉及到數(shù)據(jù)保存的問(wèn)題。雖然Activity可以通過(guò)onSaveInstanceState()機(jī)制保存與恢復(fù)數(shù)據(jù),但是onSaveInstanceState()方法只能存儲(chǔ)少量的數(shù)據(jù)進(jìn)行恢復(fù),但是遇到大量的數(shù)據(jù)該怎么辦呢?
幸運(yùn)的是,ViewModel能完美的為我們解決這個(gè)問(wèn)題,ViewModel有自己獨(dú)立的生命周期,屏幕旋轉(zhuǎn)所導(dǎo)致的Activity重建,并不會(huì)影響ViewModel的生命周期.
ViewModel 使用
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0'寫一個(gè)繼承自ViewModel的類
class MyViewModel : ViewModel() {private val users: MutableLiveData<List<User>> by lazy {MutableLiveData<List<User>>().also {loadUsers()}}fun getUsers(): LiveData<List<User>> {return users}private fun loadUsers() {// Do an asynchronous operation to fetch users.} }使用:
class MainActivity : AppCompatActivity() {override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)val mainViewModel = ViewModelProvider(this).get(MyViewModel::class.java)mainViewModel.getUsers()}}ViewModel是一個(gè)抽象類,其中只有一個(gè)onCleared()方法。當(dāng)ViewModel不再被需要,即與之相關(guān)的Activity都被銷毀時(shí),該方法會(huì)被系統(tǒng)調(diào)用。我們可以在該方法中執(zhí)行一些資源釋放的相關(guān)操作。注意: 當(dāng)屏幕旋轉(zhuǎn)而導(dǎo)致的Activity重建,并不會(huì)調(diào)用該方法。
class MyViewModel : ViewModel() {override fun onCleared() {super.onCleared()//viewModel銷毀時(shí)調(diào)用,可以做一些釋放資源的操作} }我們可以在onCleared()對(duì)定時(shí)器資源的釋放,防止造成內(nèi)存泄露。
Fragment使用
class ItemFragment : Fragment() {var mainViewModel: MyViewModel? = nulloverride fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)val mainViewModel = ViewModelProvider(requireActivity()).get(MyViewModel::class.java)}override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,savedInstanceState: Bundle?): View? {val view = inflater.inflate(R.layout.fragment_item_list, container, false)return view} }ktx 擴(kuò)展
activity 擴(kuò)展
在上面我們介紹了,在activity里獲取 viewModel 實(shí)例的方法,如下:
val mainViewModel = ViewModelProvider(this).get(MyViewModel::class.java)但是 Kotlin 的 ktx 擴(kuò)展包里面有更為簡(jiǎn)潔的方式,添加依賴如下:
implementation "androidx.activity:activity-ktx:1.3.1"使用如下:
class MainActivity : AppCompatActivity() {val mainViewModel by viewModels<MyViewModel>()override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)setContentView(R.layout.activity_main)mainViewModel.name = "hhhh"} }viewModels 擴(kuò)展方法如下:
public inline fun <reified VM : ViewModel> ComponentActivity.viewModels(noinline factoryProducer: (() -> Factory)? = null ): Lazy<VM> {val factoryPromise = factoryProducer ?: {defaultViewModelProviderFactory}return ViewModelLazy(VM::class, { viewModelStore }, factoryPromise) }fragment 擴(kuò)展
對(duì)于 fragment 我們以前是使用:
val mainViewModel = ViewModelProvider(requireActivity()).get(MyViewModel::class.java)同理,我們添加 fragment ktx 擴(kuò)展
implementation "androidx.fragment:fragment-ktx:1.3.6"就可以使用 :
val mainViewModel: MyViewModel by activityViewModels()具體代碼如下
class ItemFragment : Fragment() {val mainViewModel: MyViewModel by activityViewModels()override fun onCreate(savedInstanceState: Bundle?) {super.onCreate(savedInstanceState)}override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,savedInstanceState: Bundle?): View? {val view = inflater.inflate(R.layout.fragment_item_list, container, false)return view} }AndroidViewModel
使用ViewModel的時(shí)候,需要注意的是ViewModel不能夠持有View、Lifecycle、Acitivity引用,而且不能夠包含任何包含前面內(nèi)容的類。因?yàn)檫@樣很有可能會(huì)造成內(nèi)存泄漏。
普通的 ViewModel 生命周期都很短,隨著activity 銷毀而銷毀。如果我們要?jiǎng)?chuàng)建一個(gè)長(zhǎng)生命周期的 ViewModel 怎么辦? 其實(shí)Android 已經(jīng)給我們提供了一個(gè) AndroidViewModel
下面是一個(gè)AndroidViewModel的源碼:
public class AndroidViewModel extends ViewModel {@SuppressLint("StaticFieldLeak")private Application mApplication;public AndroidViewModel(@NonNull Application application) {mApplication = application;}/*** Return the application.*/@SuppressWarnings({"TypeParameterUnusedInFormals", "unchecked"})@NonNullpublic <T extends Application> T getApplication() {return (T) mApplication;} }可以看到 AndroidViewModel 持有了一個(gè) Application ,所以它的生命周期會(huì)很長(zhǎng)。
具體使用如下:
class MyViewModel(application: Application) : AndroidViewModel(application) {override fun onCleared() {super.onCleared()//viewModel銷毀時(shí)調(diào)用,可以做一些釋放資源的操作}}其實(shí)延伸開(kāi),我們完全可以在 AndroidViewModel 中存儲(chǔ)一些全局?jǐn)?shù)據(jù)。
總結(jié)
以上是生活随笔為你收集整理的Android ViewModel详解的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Android 应用目录分析
- 下一篇: Android Kotlin Corou