美文网首页jetpackJetpackandroid技术
Jetpack mvvm 三部曲(一) ViewModel

Jetpack mvvm 三部曲(一) ViewModel

作者: 三月四晴 | 来源:发表于2020-09-30 12:27 被阅读0次

    先说明此系列都是用Java的不是Kotlin( ps.虽然我也想用kotlin但实力不允许)

    Jetpack mvvm 三部曲(二) LiveData

    官方的Jetpack的链接

    ViewModel

    提前放下本jetpak系列自己学习期间写的demo jetpackDemo

    了解ViewModel

    • ViewModel是jetpack系列里面的一个库可以用它来管理页面的全局变量,通过它来绑定Activity和Fragment的生命周期,比如页面在手机横屏时会重新走一次生命周期要没有重新onSaveInstanceState方法进行数据保存的话,这个时候全局变量数据会丢失或者说被重新初始化,这个时候用它进行数据保护就会简单甚至什么操作都不需要。
    • 由于ViewModel比被绑定的Activity和Fragment的生命周期更长在页面onDestroy的时候ViewModel还没销毁结束,所以不要在ViewModel持有Context的引用或者持有Context类。
    官方给的生命周期对比图 官方也强烈注意

    使用ViewModel

    • 使用之前请确保项目已经用上了AndroidX 虽然Support 也有LiveData、ViewModel、DataBinding这些库,但是在2018年I/O大会后就不在去更新了。
    • 在项目的build.gradle文件引用
    allprojects {
        repositories {
            google()
            jcenter()
        }
    }
    
    • 在项目App目录的build.gradle文件引用,我这里的版本是2.2.0的版本( 目前最新的) 其余版本可参考
    dependencies {
        implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0"
    }
    
    • 完成了库的引用剩下的就是快乐编码了
    • 第一步直接新建一个类继承ViewModel
    public class MyViewModel extends ViewModel {
        private User user;
        private int count;
        public User getUser() {
            return user;
        }
    
        public void setUser(User user) {
            this.user = user;
        }
    
        public int getCount() {
            return count;
        }
    
        public void setCount(int count) {
            this.count = count;
        }
    }
    
    • 第二步使用 在Activity和Fragme使用它
    • Activity中
    protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main)
            MyViewModel viewModel = new ViewModelProvider(this).get(MyViewModel.class);
            textView = findViewById(R.id.text);
            if(viewModel.getUser()!=null){
                refreshText();
            }
    }
    //这里是一个按钮的点击时间
      public void addUser(View view){
            User user  = new User();
            user.setName("张三");
            user.setAge(18);
            viewModel.setUser(user);
            refreshText();
        }
    public void refreshText(){
            textView.setText(viewModel.getUser().getName()+"今年"+viewModel.getUser().getAge()+"岁");
      }
    
    • 到这里就Activity中使用就结束了,横竖屏切换看下Textview


      image.png
      image.png
    • 这里最关键的是new ViewModelProvider(this) this传入了一个ViewModelStoreOwner,关联绑定生命周期的就是它 。ViewModelStoreOwner这个是在androidX的ComponentActivity类已经帮我们实现了的接口
      image.png
    • 这样意味activity和fragment 也可以共享一个ViewModel了,Fragment的实现请继承androidx.fragment.app.Fragment 因为androidx的fragment已经实现了ViewModelStoreOwner接口。
    androidx.fragment.app.Fragment
     public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
            rootView = (TextView) inflater.inflate(R.layout.fragment_view_model,container,false);
            //这里表示和activity共享一个
            viewModel = new ViewModelProvider((ViewModelStoreOwner) getActivity()).get(MyViewModel.class);
            //单独私有的
            viewModel1 = new ViewModelProvider(this).get(MyViewModel.class);
            if(viewModel.getUser()!=null){
                rootView.setText(viewModel.getUser().getName()+"今年"+viewModel.getUser().getAge()+"岁");
            }
            return rootView;
        }
    
    • 有了上面的ViewModel的认知,这时我们除了activity与fragment的数据共享,还可以设定一个全局的ViewModel。
    public class MyApplication extends Application implements ViewModelStoreOwner {
        private static ViewModelStore viewModelStore;
        private MainViewModel mainViewModel;
        public static ViewModelStoreOwner viewModelStoreOwner;
    
        @Override
        public void onCreate() {
            super.onCreate();
            viewModelStore = new ViewModelStore();
            mainViewModel = new ViewModelProvider(this).get(MainViewModel.class);
            viewModelStoreOwner = this;
        }
    
        public static ViewModelStoreOwner getViewModelStoreOwner() {
            return viewModelStoreOwner;
        }
    
        @NonNull
        @Override
        public ViewModelStore getViewModelStore() {
            return viewModelStore;
        }
    }
    
    • 在Activity使用这个全局的ViewModel
     MainViewModel  mainViewModel = new ViewModelProvider((MyApplication) getApplication()).get(MainViewModel.class);
    
    • 到此ViewModel你大概应该有了基础的用法了,最后在说一个ViewModel的构造方法中进行数据初始化。
    public class MyViewModel extends ViewModel {
        private User user;
        private int count;
    
        public MyViewModel() {
            this.user = new User("张三",11);
            this.count = 13;
        }
    
        public User getUser() {
            return user;
        }
    
        public void setUser(User user) {
            this.user = user;
        }
    
        public int getCount() {
            return count;
        }
    
        public void setCount(int count) {
            this.count = count;
        }
    }
    
    • 相比上面的ViewModel就多了个无参构造方法对user进行了实例化
    • 下面看下有参构造构造方法进行数据初始化加一个有参构造方法
     public MyViewModel(User user, int count) {
            this.user = user;
            this.count = count;
        }
    
    • 重点来了先得知ViewModel的实例化是通过反射进行实例化return的
    • 具体代码如下
    • 图一这里实现ViewModel
    • 图二是ViewModelProvider的构造方法,注意红框地方 传递的owner是不满足这个三元运算的只传递红框默认值
    • 图3.1、3.2是静态类部类NewInstanceFactory的全部代码(ps.没法截完整就搞2个图)
      我们看到NewInstanceFactory实现了Factory接口类create方法
    • 图4、图5就是get方法的代码重点部分注意红框
    图1
    图2
    图3.1 图3.2
    图4
    图5
    • 看完上面是不是有了个大胆的推测。怎么去实现有参构造方法的ViewModel了,我们依照NewInstanceFactory葫芦画瓢实现Factory就好了。
    public class MainViewModelFactory implements ViewModelProvider.Factory {
        private String name;
        private int age;
    
        public MainViewModelFactory(String name, int age) {
            this.name = name;
            this.age = age;
        }
    
        @NonNull
        @Override
        public <T extends ViewModel> T create(@NonNull Class<T> modelClass) {
            return (T) new MyViewModel(new User(name,age),11);
        }
    }
    
     MyViewModel viewModel = new ViewModelProvider(this,new MainViewModelFactory("张三",11)).get(MyViewModel.class);
    
    • 到此对ViewModel的认知和使用就掌握了

    本人也是刚介入Jetpack 写的不对不好的地方请大家指点

    感兴趣的可以继续看这篇稍微深入扯下Jetpack的ViewModel

    相关文章

      网友评论

        本文标题:Jetpack mvvm 三部曲(一) ViewModel

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