美文网首页
ViewModel简介

ViewModel简介

作者: 豚豚酱_0cbc | 来源:发表于2020-09-10 16:11 被阅读0次

Viewmodel

官方介绍

ViewModel is a class that is responsible for preparing and managing the data for an Activity or a Fragment. It also handles the communication of the Activity / Fragment with the rest of the application (e.g. calling the business logic classes).

特点:

1.单一职责,将数据从业务中抽离出来。即只要是界面上看的到的数据,相关变量都应该存放在ViewModel,而不是Activity中
2.生命周期长,存在于所属对象(Activity,Fragment)的全部生命周期。
3.扩展性好,方便与其他功能组合,例如Livedata,room

使用场景:

1.横竖屏切换,Activity重建,数据可依然保存
2.同一个Activity下,Fragment之间的数据共享

注意事项

1.不能将context或带有Context引用的对象传入ViewModel中,这可能会导致页面无法被销毁,从而导致内存泄漏
2.同一个Activity下的fragment通过ViewModel进行数据共享时,ViewModel的拥有者是Activity,传参要注意。
3.一个Activity对应一个ViewModel

基本用法

添加依赖

implementation 'androidx.lifecycle:lifecycle-extensions:2.1.0'

相关代码

新建一个MainActivity对应的MainViewModel类,并让它继承自ViewModel,加一个变量counter用于计数

class MainactyViewModel : ViewModel() {
    var counter = 0;
    /**
     * 与之相关的Activity被销毁时,该方法会被系统调用。我们可以在该方法中执行一些资源释放的相关操作
     */
    override fun onCleared() {
        super.onCleared()
    }

}

在布局界面添加一个按钮,每点击一次按钮,就让计数器加1,并把最新计数显示出来

        <RelativeLayout
            android:layout_below="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="match_parent">

            <TextView
                android:id="@+id/tv_counter"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerInParent="true"
                android:text="0"
                android:textStyle="bold"
                android:textSize="20sp"/>
            <TextView
                android:id="@+id/tv_counter2"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_below="@+id/tv_counter"
                android:text="0"
                android:textStyle="bold"
                android:textSize="20sp"
                android:layout_centerHorizontal="true"/>
            <Button
                android:id="@+id/btn_plus"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="+1"
                android:layout_below="@+id/tv_counter2"/>
        </RelativeLayout>

在MainActivity中实现计数器逻辑

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        viewModel = ViewModelProviders.of(this).get(MainactyViewModel::class.java)
        btn_plus.setOnClickListener{
            viewModel.counter++
            counter2++
            refreshCounter()
        }
        refreshCounter()
    }
    private fun refreshCounter() {
        tv_counter.setText(viewModel.counter.toString())
        tv_counter2.setText(counter2.toString())
    }

我们不能直接去创建ViewModel的实例,而是一定要通过ViewModelProviders来获取ViewModel的实例,具体语法规则如下:

ViewModelProviders.of(<Activity或者Fragment实例>).get(<ViewModel>::class.java)

之所以这么写,是因为viewModel的生命周期长于Activity.如果我们在onCreate()方法中创建ViewModel的实例,那么每次onCreate方法执行的时候,ViewModel都会创建一个新的实例,当手机屏幕发生旋转的时候,就无法保留其中的数据。

测试结果

点击+1按钮三次,tv_counter和tv_counter2的值均为3,将屏幕旋转,tv_counter的值为3,tv_counter2的值为0,再次点击+1按钮,tv_counter值为4,tv_counter2值为1

向ViewModel传递参数

在大多数情况下,我们需要通过构造函数来传递一些参数,我们可以借助ViwModelProvider.Factory来实现

相关代码

给MainactyViewModel的构造函数添加一个counter参数

class MainactyViewModel(counter : Int) : ViewModel() {
    var counter = counter;
}

新建一个MainViewModelFactory类并实现ViwModelProvider.Factory接口,create方法执行的时机和Activity的周期无关,因此可以创建MainViewModel的实例

class MainViewModelFactory(private var counter :Int) : ViewModelProvider.Factory{
    override fun <T : ViewModel?> create(modelClass: Class<T>): T {
        return MainactyViewModel(counter) as T
    }
}

在MainActivity中使用

viewModel = ViewModelProviders.of(this,MainViewModelFactory(counter2)).get(MainactyViewModel::class.java)

AndroidViewModel

前面提到了,在使用ViewModel的时候,不能将Context传入ViewModel。但如果实际运用中,的确需要使用context,此时可以使用AndroidViewModel类。该类继承自ViewModel,并接收Application作为Context,这意味着它的生命周期和Application是一样的。

相关文章

网友评论

      本文标题:ViewModel简介

      本文链接:https://www.haomeiwen.com/subject/ldppektx.html