Android ViewModel详解
轉載請標明出處:http://blog.csdn.net/zhaoyanjun6/article/details/119828016
本文出自【趙彥軍的博客】
文章目錄
- ViewModel簡介
- ViewModel生命周期
- ViewModel 使用
- Fragment使用
- ktx 擴展
- activity 擴展
- fragment 擴展
- AndroidViewModel
ViewModel簡介
視圖與數據模型之間的橋梁ViewModel
ViewModel生命周期
ViewModel的生命周期會比創建它的Activity、Fragment的生命周期都要長。即ViewModel中的數據會一直存活在Activity/Fragment中。
眾所周知,由于Android平臺的特殊性,若應用程序發送屏幕旋轉的時候會經歷Activity的銷毀與重建,這里就涉及到數據保存的問題。雖然Activity可以通過onSaveInstanceState()機制保存與恢復數據,但是onSaveInstanceState()方法只能存儲少量的數據進行恢復,但是遇到大量的數據該怎么辦呢?
幸運的是,ViewModel能完美的為我們解決這個問題,ViewModel有自己獨立的生命周期,屏幕旋轉所導致的Activity重建,并不會影響ViewModel的生命周期.
ViewModel 使用
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0'寫一個繼承自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是一個抽象類,其中只有一個onCleared()方法。當ViewModel不再被需要,即與之相關的Activity都被銷毀時,該方法會被系統調用。我們可以在該方法中執行一些資源釋放的相關操作。注意: 當屏幕旋轉而導致的Activity重建,并不會調用該方法。
class MyViewModel : ViewModel() {override fun onCleared() {super.onCleared()//viewModel銷毀時調用,可以做一些釋放資源的操作} }我們可以在onCleared()對定時器資源的釋放,防止造成內存泄露。
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 擴展
activity 擴展
在上面我們介紹了,在activity里獲取 viewModel 實例的方法,如下:
val mainViewModel = ViewModelProvider(this).get(MyViewModel::class.java)但是 Kotlin 的 ktx 擴展包里面有更為簡潔的方式,添加依賴如下:
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 擴展方法如下:
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 擴展
對于 fragment 我們以前是使用:
val mainViewModel = ViewModelProvider(requireActivity()).get(MyViewModel::class.java)同理,我們添加 fragment ktx 擴展
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的時候,需要注意的是ViewModel不能夠持有View、Lifecycle、Acitivity引用,而且不能夠包含任何包含前面內容的類。因為這樣很有可能會造成內存泄漏。
普通的 ViewModel 生命周期都很短,隨著activity 銷毀而銷毀。如果我們要創建一個長生命周期的 ViewModel 怎么辦? 其實Android 已經給我們提供了一個 AndroidViewModel
下面是一個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 持有了一個 Application ,所以它的生命周期會很長。
具體使用如下:
class MyViewModel(application: Application) : AndroidViewModel(application) {override fun onCleared() {super.onCleared()//viewModel銷毀時調用,可以做一些釋放資源的操作}}其實延伸開,我們完全可以在 AndroidViewModel 中存儲一些全局數據。
總結
以上是生活随笔為你收集整理的Android ViewModel详解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Android 应用目录分析
- 下一篇: Android Kotlin Corou