Jetpack探秘系列(一)----ViewModel

传统的开发模式中,大多数的处理逻辑和数据都是写在Activity和Fragment,导致两者代码臃肿,因此产生了诸如MVP,MVVM的架构,而ViewModel正是实现MVVM架构最重要的组件之一。

ViewModel最重要的作用就是存放Activity和Fragment相关的数据,可以理解为存放页面所有数据的容器,那么问题来了,将数据和界面显示逻辑分开确实能让整体逻辑更清晰,但是为什么数据需要放在ViewModel,它和我们直接新建一个类来保存数据差别优点在哪?

其中使用ViewModel最重要的是它的生命周期并不是和Activity和Fragment完全同步,它生命周期更长,如下图,Activity/Fragment的onDestroy之外的其他生命周期都是ViewModel对象的生存期,只有Activity/Fragment销毁,ViewModel才会被销毁。最重要的是,正常手机横竖屏切换的时候Activity/Fragment需要被重建,同时数据也会清除,在这种重建过程中,Activity/Fragment会执行onDestroy操作,而ViewModel在这种情况下不会清除,只有Activity/Fragment退出时的onDestroy才会结束它的生命周期,因此ViewModel能更持久的保留数据。

通常情况下,建议一个Activity/Fragment对应一个ViewModel,界面保存各自的数据,ViewModel只提供数据的更改和获取操作,任何数据的逻辑处理都应该写在Activity/Fragment中。

为什么不能直接new的方式来新建ViewModel?因为ViewModel的生命周期和Activity/Fragment不一样,如果直接new的方式获得ViewModel,那么后者的生命周期将和前者完全同步

public class MyViewModel extends ViewModel {
    int count = 0;
}
import androidx.lifecycle.ViewModelProvider;  //1

public class MainActivity extends AppCompatActivity {
    MyViewModel myViewModel;
    TextView textView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        myViewModel = new ViewModelProvider(this).get(MyViewModel.class);
        textView = findViewById(R.id.textview);
        textView.setText(String.valueOf(++myViewModel.count));
    }
}

 

[番外知识点]

有些同学在执行2的时候发现this下面报错,ViewModelProvider找不到对应的构造函数,这个原因主要是拓展库默认的是2.1.0的ViewModel版本,而在2.1.0的时候ViewModel只有下面两个构造函数

public ViewModelProvider(ViewModelStoreOwner owner, Factory factory) 
public ViewModelProvider(ViewModelStore store, Factory factory)

而在ViewModel2.2.0版本中新增了

public ViewModelProvider(@NonNull ViewModelStoreOwner owner)

因此只有显性的在模块gradle.build中引入2.2.0库即可

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

 

有参ViewModel的实例化

上述例子只能在无参ViewModel的实例化情况下才能使用,而由于生命周期的原因,有参ViewModel的实例化肯定也无法使用new的方式来获取ViewModel对象,因此需要借用实现了ViewModelProvider.Factory的类来实例化,具体来说,该接口的create不依赖Activity/Fragment的生命周期,因此可以使用create获得ViewModel对象

public class MyViewModel extends ViewModel {
    int count = 0;

    public MyViewModel(int count) {
        this.count = count;
    }
}
public class MyViewModelFactory implements ViewModelProvider.Factory {
    int count = 0;

    private MyViewModelFactory() {
    }

    public MyViewModelFactory(int count) {
        this.count = count;
    }
    @NonNull
    @Override
    public <T extends ViewModel> T create(@NonNull Class<T> modelClass) {
        return (T) new MyViewModel(count);
    }
}
public class MainActivity extends AppCompatActivity {
    MyViewModel myViewModelFactory;
    TextView textView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        textView = findViewById(R.id.textview);

        myViewModelFactory = new MyViewModelFactory(99).create(MyViewModel.class);
        textView.setText(String.valueOf(++myViewModelFactory.count));
    }
}

 从上述例子我们可以归纳ViewModel的一些特征:

  • ViewModel类似于一个数据类,作为具体数据存放的容器,生命周期由父类ViewModel掌控,自定义子类只需要关注数据的存取
  • 建议一个Activity/Fragment对应一个ViewModel
  • Activity/Fragment获取数据必须要获得自定义ViewModel对象,同时获取方式必须通过ViewModelProvider(无参情况)和ViewModelProvider.Factory对象(有参情况),以此来达到与Activity/Fragment不同的生命周期(具体实现逻辑请看后文源码分析)
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值