文章目录
- Jetpack ViewModel
- 概述
- 添加依赖库
- ViewModel的生命周期
- 基本使用
- AndroidViewModel
- Fragment之间共享数据
- ViewModel与onSaveInstanceState()区别
- 代码下载
Jetpack ViewModel
概述
ViewModel 类目的在于以注重生命周期的方式存储和管理界面相关数据。ViewModel类让数据可在发生屏幕旋转等配置更改后继续留存。
添加依赖库
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13//ktx implementation "androidx.activity:activity-ktx:1.2.3" implementation "androidx.fragment:fragment-ktx:1.3.6" //Lifecycle def lifecycle_version = "2.5.0" //LiveData implementation "androidx.lifecycle:lifecycle-livedata-ktx:$lifecycle_version" implementation "androidx.lifecycle:lifecycle-common-java8:$lifecycle_version" implementation "androidx.lifecycle:lifecycle-process:$lifecycle_version" //ViewModel implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:$lifecycle_version"
ViewModel的生命周期
ViewModel
对象存在的时间范围是获取 ViewModel
时传递给 ViewModelProvider
的 Lifecycle
。ViewModel
将一直留在内存中,直到限定其存在时间范围的 Lifecycle
永久消失:对于 Activity,是在 Activity 完成时;而对于 Fragment,是在 Fragment 分离时。
由于ViewModel的生命周期长于Activity,因此不能将View或者Activity的context传给ViewModel,否则会引起内存泄露。
基本使用
ViewModel类实现
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15class MyViewModel : ViewModel() { private val _countLiveData = MutableLiveData<Int>() val countLiveData = _countLiveData private var count = 0 fun increase() { _countLiveData.postValue(++count) } fun decrease() { _countLiveData.postValue(--count) } }
获取ViewModel对象,方式一
复制代码
1
2var viewModel: MyViewModel = ViewModelProvider(this).get(MyViewModel::class.java)
获取ViewModel对象,方式二
复制代码
1
2val viewModel: MyViewModel by viewModels()
在Activity中使用
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43class ViewModelSimpleActivity : BaseActivity() { private lateinit var tvCount: TextView private lateinit var tvScreen: TextView private val viewModel: MyViewModel by viewModels() override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_view_model_simple) Log.e(VIEWMODEL, "onCreate") initView() val screenOrientation = if (resources.configuration.orientation == Configuration.ORIENTATION_PORTRAIT) "竖屏" else "横屏" tvScreen.text = "屏幕方向:$screenOrientation" viewModel.countLiveData.observe(this, object : Observer<Int> { override fun onChanged(t: Int?) { Log.e(VIEWMODEL, "onChanged") tvCount.text = t.toString() } }) } private fun initView() { tvCount = findViewById(R.id.tv_count) tvScreen = findViewById(R.id.tv_screen) } fun clickIncrease(v: View) { viewModel.increase() } fun clickDecrease(v: View) { viewModel.decrease() } override fun onDestroy() { super.onDestroy() Log.e(VIEWMODEL, "onDestroy") } }
AndroidViewModel
因为ViewModel对象的存活时间较长,因此不能将Activity的Context传递给ViewModel,否则会引起内存泄露。如果需要使用context,这时可以使用AndroidViewModel接收Application的对象。
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15class MyAndroidViewModel(application: Application) : AndroidViewModel(application) { private val _countLiveData = MutableLiveData<Int>() val countLiveData = _countLiveData private var count = 0 fun increase() { _countLiveData.postValue(++count) } fun decrease() { _countLiveData.postValue(--count) } }
Fragment之间共享数据
优点:
- Activity不需要做其他操作
- Fragment之间没有任何干扰,只需要约定ViewModel
SharedViewModel类
复制代码
1
2
3
4
5
6
7
8
9class SharedViewModel : ViewModel() { private val _liveData = MutableLiveData<String>() val liveData = _liveData fun select(item: String) { _liveData.postValue("$item detail") } }
Activity类
复制代码
1
2
3
4
5
6
7
8
9
10
11class MenuActivity : BaseActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_menu) supportFragmentManager.beginTransaction() .add(R.id.fl_menu, MenuFragment.newInstance()) .add(R.id.fl_detail, DetailFragment.newInstance()) .commit() } }
MenuFragment
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30class MenuFragment : BaseFragment() { private val sharedViewModel: SharedViewModel by activityViewModels() companion object { fun newInstance() = MenuFragment() } override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { // Inflate the layout for this fragment return inflater.inflate(R.layout.fragment_menu, container, false) } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) val listView = view.findViewById<ListView>(R.id.listView) val data = ArrayList<String>().apply { for (i in 0..20) { add("menu$i") } } listView.adapter = ArrayAdapter(mContext, android.R.layout.simple_list_item_1, data) listView.setOnItemClickListener { parent, view, position, id -> sharedViewModel.select(data[position]) } } }
DetailFragment
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25class DetailFragment : BaseFragment() { private val sharedViewModel: SharedViewModel by activityViewModels() companion object { fun newInstance() = DetailFragment() } override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { return inflater.inflate(R.layout.detail_fragment, container, false) } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) val textView = view.findViewById<TextView>(R.id.textView) sharedViewModel.liveData.observe(viewLifecycleOwner, object : Observer<String> { override fun onChanged(t: String?) { textView.text = t } }) } }
ViewModel与onSaveInstanceState()区别
- ViewModel:适用于配置变更导致的数据恢复,这是因为内存容量相对较大,可以存储较多的数据。
- onSaveInstanceState():适用于被系统回收后重建时的数据恢复,这是因为系统回收时应用进程会消亡,因此不能用内存存储而是使用持久化存储,同时这部分数据需要通过Bundle机制传输数据,Bundle缓冲区有大小限制,只能适用于小规模数据。
ViewModel | onSaveInstanceState() | |
---|---|---|
存储方式 | 在内存中 | 序列化在磁盘 |
读写效率 | 高(内存中访问) | 较慢(需要序列化、反序列化操作) |
配置更改后,数据是否留存 | 是 | 否 |
系统回收后,数据是否留存 | 否 | 是 |
使用场景 | 屏幕旋转等配置更改后保存 | Activity异常销毁时才会被调用 |
存储限制 | 可存储复杂数据,存储大小受App可用内存影响 | 只能存储可序列化对象,有存储大小有限制(一般为1M) |
代码下载
最后
以上就是爱笑铃铛最近收集整理的关于Android ViewModel使用Jetpack ViewModel的全部内容,更多相关Android内容请搜索靠谱客的其他文章。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复