Android  JetPack~ ViewModel (一)   介绍与使用

 
ViewModel,MVVM框架中的一部分,他主要作用是处理业务逻辑、数据分配等,他是Mode和VIew连接的桥梁,和MVP相比,他类似P。
ViewModel类有如下优点:
  1. ViewModel类是具有生命感知的能力,与和他绑定的Activity一样的生命周期,它可以解决请求网络时,Activity被突然销毁造成一些不必要的麻烦。
  2. 设备信息发生变更数据不会丢失(切横竖屏),其实它只有一个生命周期,检测页面销毁时触发
  3. ViewModel 的另一个特点就是同一个 Activity 的 Fragment 之间可以使用ViewModel实现共享数据。
  4. 每个Activity绑定的ViewModel都是独立的(Activity之间)

没用的小忠告

有些问题,可能没有深度。
有一次一个面试官问我,Q:你知道ViewModel是如何和Acvitity绑定的吗?我当时大脑在想1、他是不是问我内部实现?2、简单用法?我猜是第一,不然第二种的话,有啥可问的。当时我说:我不知道。他诧异的看着我,你不是使用过MVVM框架吗?不知道怎么用ViewModel吗。我不自信的说了句是通过ViewModelProvider。他来了一句是,是这个,后面问了我好多很简单的问题,当时给我整无语了,怎么全是这咋用,那咋用,一点深度都没有,却给我搞的很不自信,因为好多使用步骤平常不复习,就很容易忘,我当时就觉得这小子水平估计也不咋样,离场后果断删除了他们人事的联系方式。
 
Android  JetPack~ ViewModel (一)   介绍与使用

Android  JetPack~ ViewModel (一)   介绍与使用1、开始使用

添加依赖

以前是需要添加依赖的,现在 方式一: implementation 'androidx.appcompat:appcompat:1.2.0',//这里面也包含ViewModel,LiveData等,      方式二: 也可以单独添加 implementation "androidx.fragment:fragment:1.1.0" implementation "androidx.lifecycle:lifecycle-viewmodel:2.1.0" implementation "androidx.lifecycle:lifecycle-extensions:2.1.0"

2、Activity

2.1、新建ViewModel

public class MyViewModel extends ViewModel {      @Override     protected void onCleared() {         super.onCleared();     } }

onCleared方法是ViewModel独有的,当Activity销毁后,它会调用,所以我们可以在这取消网络请求等。平常开发中不做任何操作时,如果有网络请求中,Activity被销毁,那么极有可能请求成功返回结果到activity中造成泄漏等不必要的麻烦。

解决方式:

可以使用ViewModel,结合onCleared(),call.cancel()等去做。
网络请求时,突然销毁activity,那么与之绑定的viewmodel也会销毁,同时我们在onCleared()方法中取消网络连接接口(call.cancel()),就算是有数据返回,activity也不会收到通知,因为数据是从livedata中监听的,只有livedata触发了更新,Activity才会收到通知。
(当然还有很多其他方式)
 

2.2、绑定Activity

这里有如下方式:
  • ViewModelProviders.of(this).get(class)(过时)
  • new ViewModelProvider(this,factory).get(class)(常用)
  • new ViewModelProvider.NewInstanceFactory().create(class);
 

第一种方式:ViewModelProviders.of(this).get(class)

ViewModelProviders.of(this).get(MyViewModel.class);   implementation "androidx.fragment:fragment:1.1.0" implementation "androidx.lifecycle:lifecycle-viewmodel:2.1.0" implementation "androidx.lifecycle:lifecycle-extensions:2.1.0"

这种方式是这些依赖中的,当然,如果你的和我的不一样,也无所谓,这不是重点。这个方式比较老了,在源码中也能发现,ViewModelProviders的of方法其实也是调用了ViewModelProvider,自动创建了一个factory。
----------------ViewModelProviders.class----------------  @NonNull @MainThread public static ViewModelProvider of(@NonNull Fragment fragment, @Nullable Factory factory) {     Application application = checkApplication(checkActivity(fragment));     if (factory == null) {         factory = ViewModelProvider.AndroidViewModelFactory.getInstance(application);     }     return new ViewModelProvider(fragment.getViewModelStore(), factory); }

 
 

第二种方式:new ViewModelProvider(this,factory).get(class)

ViewModelProvider(this, new ViewModelProvider.NewInstanceFactory()).get(MyViewModel.class);

传入一个系统的factory。create是创建一个新的实例,而get是先从HashMap中找,找不到就创建新的实例。也是为什么重建的Viewmodel是同一个对象的原因,他会把对象放在ViewModelStore类中HashMap<String, ViewModel> mMap = new HashMap<>();中。这个方式比较新,一般也是这样创建。
 
public <T extends ViewModel> T get(@NonNull String key, @NonNull Class<T> modelClass) {     //第一步:先查找     ViewModel viewModel = mViewModelStore.get(key);      if (modelClass.isInstance(viewModel)) {         //noinspection unchecked         return (T) viewModel;     } else {         //noinspection StatementWithEmptyBody         if (viewModel != null) {             // TODO: log a warning.         }     }     //第二步:没有则创建,并保存在mViewModelStore中     if (mFactory instanceof KeyedFactory) {         viewModel = ((KeyedFactory) (mFactory)).create(key, modelClass);     } else {         viewModel = (mFactory).create(modelClass);     }     mViewModelStore.put(key, viewModel);     //noinspection unchecked     return (T) viewModel; }

第三种方式:new ViewModelProvider.NewInstanceFactory().create(class);

MyViewModel myViewModel1 = new ViewModelProvider.NewInstanceFactory().create(MyViewModel.class);

 
 
下面写一个LiveData,如果对LiveData不懂的可以翻看之前的博客,目录在顶部
public class MyViewModel extends ViewModel {     private MutableLiveData<String> mStr= new MutableLiveData<>();      public MutableLiveData<String> getmStr() {         return mStr;     }     public void setmStr(String s) {         if(mStr==null){             mStr = new MutableLiveData<>();         }         mStr.setValue(s);     }     @Override     protected void onCleared() {         super.onCleared();     } }

全部代码
public class JPackActivity extends AppCompatActivity {      private ActyJpackLayoutBinding mBinding;     private MyViewModel myViewModel;      @Override     protected void onCreate(@Nullable Bundle savedInstanceState) {         super.onCreate(savedInstanceState);         //通过databinding 把activity和view绑定         mBinding = DataBindingUtil.setContentView(this,R.layout.acty_jpack_layout);         //通过ViewModeProvider 把activity和ViewModel绑定起来。         myViewModel = new ViewModelProvider(this, new ViewModelProvider.NewInstanceFactory()).get(MyViewModel.class);          myViewModel.getmStr().observe(this, new Observer<String>() {             @Override             public void onChanged(String s) {                 mBinding.textShow.setText(s);             }         });     }     @Override     protected void onDestroy() {         super.onDestroy();         //移除观察者             }

 

3、Fragment

使用和Activity中一样。不过需要注意的是传入this和getActivity的区别
  • this:这个ViewModel是独立的,只为这个Fragment单独服务,其他Fragment无法获取到相同内存地址的ViewModel
  • getActivity:使用getActivity()获得的ViewModel 作用域在Activity里和所有他创建碎片的里,意思是你在其他Fragment也获取相同内存地址的ViewModel
 
 @Override public View onCreateView(LayoutInflater inflater, ViewGroup container,                          Bundle savedInstanceState) {     // Inflate the layout for this fragment     MyViewModel myViewModel = new ViewModelProvider(getActivity(), new ViewModelProvider.NewInstanceFactory()).get(MyViewModel.class);     return inflater.inflate(R.layout.fragment_blank, container, false); }

 
当然还有一个注意点get("key1",MyViewModel.class);,get方法可以传key值,不同的key创建的ViewModel数据是独立的
 

4、总结

使用起来非常简单,还要多加练习,才不会被那些xx面试官问步骤咋实现难住。
 

发表评论

评论已关闭。

相关文章

  • 0