首页 > 技术文章 > Android开发 ViewModel_1_了解与简单使用

guanxinjing 2019-09-18 20:32 原文

前言

  ViewModel是google推出的一个数据处理框架,ViewModel类是被设计用来以可感知生命周期的方式存储和管理 UI 相关数据ViewModel中数据会一直存活即使 activity configuration发生变化.另外它生来可能目的就是与Fragment在数据共享上进行配合的.

使用它常与LiveData数据前台类(类似观察者模式的数据实体回调类)进行配合以前使用,如果你未了解LiveData建议你先了解它Android开发 LiveData与MutableLiveData详解 然后在回头在来看这篇博客

  在总结下有的这些特征:

1.让数据与UI隔离:让ViewModel来获取数据加工数据并且回调给UI层.明确职责工作分离(参考MVP,MVVM这些框架结构)

2.数据与生命周期绑定:ViewModel与注册的Activity的生命周期绑定,有着与Activity同步的生命周期,如下图.这样就算网络请求的数据的异步回来后Activity已经销毁也不会出现问题,因为ViewModel也会被销毁终止数据的回调.

 

3.数据持久化:ViewModel不会因为屏幕的旋转导致Activity重新创建而重置数据.(这样避免了Activity被旋转数据丢失的问题)

4.与其他Activity独立:ViewModel的数据是独立的,它跟每一个绑定的Activity都是实例一个单独的数据(意思是它无法跟多个Activity绑定后同步共享数据)

5.天生为了配合Fragment:ViewModel可以与一个Activity与多个Fragment绑定后共享数据.(你终于可以不用很蛋疼的把Fragment的数据暂存到Activity里了)并且可以都与他们的生命周期关联.这样Fragment短暂的生命周期将不在让你烦恼数据的暂存问题.

依赖

    implementation "androidx.fragment:fragment:1.1.0"
    implementation "androidx.lifecycle:lifecycle-viewmodel:2.1.0"
    implementation "androidx.lifecycle:lifecycle-extensions:2.1.0"

androidx.lifecycle:lifecycle-extensions:2.1.0 是ViewModelProviders的实现依赖,如果不导入就没有这个。

创建与绑定Activity

创建ViewModel

public class DemoViewModel extends ViewModel {
    // TODO: Implement the ViewModel

    @Override
    protected void onCleared() {
        super.onCleared();
        //清除的方法,这个方法需要让你处理一些网络请求的停止或者数据加工的逻辑停止,它与绑定的Activity在销毁的时候触发.你不需要手动在Activity里调用它
    }
}

 

绑定Activity

public class Demo1Activity extends AppCompatActivity {
    private static final String TAG = "Demo1Activity";
    private DemoViewModel mDemoViewModel;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_demo);
        mDemoViewModel = ViewModelProviders.of(this).get(DemoViewModel.class);//获取ViewModel,让ViewModel与此activity绑定
        
    }
}

以上简单继承和注册后就与Activity绑定了,它是单例模式的这点你可以在of()方法里看到它实现了单例(一个Activity只有一个单例),另外在Fragment的方式也是与Activity相同的方式如下:

mViewModel = ViewModelProviders.of(getActivity()).get(DemoViewModel.class);

这样你就将Activity和Fragment之间可以用ViewModel进行数据上的共享与同步了

 

简单的demo

   实际使用的时候是与LiveData一起配合使用的,这里提供一个简单的demo了解下实际使用.

创建LiveData类

public class DemoData extends LiveData<DemoData> {
    private int tag1;
    private int tag2;

    public int getTag1() {
        return tag1;

    }
    public void setTag1(int tag1) {
        this.tag1 = tag1;
        postValue(this);
    }

    public int getTag2() {
        return tag2;
    }

    public void setTag2(int tag2) {
        this.tag2 = tag2;
        postValue(this);
    }
}

创建ViewModel并且在内部实例化LiveData

public class DemoViewModel extends ViewModel {
    // TODO: Implement the ViewModel
    private DemoData mDemoData = new DemoData();

    public DemoData getDemoData() {
        return mDemoData;
    }

    @Override
    protected void onCleared() {
        super.onCleared();
        //清除的方法,这个方法需要让你处理一些网络请求的停止或者数据加工的逻辑停止
    }
}

绑定Activity,模拟数据变化

public class Demo2Activity extends AppCompatActivity {
    private static final String TAG = "Demo2Activity";
    private Button mBtnAddData;
    private DemoViewModel mDemoViewModel;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_demo2);
        mBtnAddData = findViewById(R.id.btn_add_data);
        mDemoViewModel = ViewModelProviders.of(this).get(DemoViewModel.class);//获取ViewModel,让ViewModel与此activity绑定
        mDemoViewModel.getDemoData().observe(this, new Observer<DemoData>() { //注册观察者,观察数据的变化
            @Override
            public void onChanged(DemoData demoData) {
                Log.e(TAG, "onChanged: 数据有更新");
            }
        });

        mBtnAddData.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Log.e(TAG, "onClick: 已经点击");
                mDemoViewModel.getDemoData().setTag1(123); //这里手动用按键点击更新数据

            }
        });
    }
}

绑定Fragment

public class DemoFragment extends Fragment {
    private static final String TAG = "DemoFragment";
    private DemoViewModel mViewModel;

    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container,
                             @Nullable Bundle savedInstanceState) {
        return inflater.inflate(R.layout.demo1_fragment, container, false);
    }

    @Override
    public void onActivityCreated(@Nullable Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        // TODO: Use the ViewModel
        mViewModel = ViewModelProviders.of(getActivity()).get(DemoViewModel.class);
        mViewModel.getDemoData().observe(this, new Observer<DemoData>() {
            @Override
            public void onChanged(DemoData demoData) {
                Log.e(TAG, "onChanged: 数据有更新");
                
            }
        });

    }
}

Fragment绑定ViewModel , of(getActivity())与of(this)的区别

mViewModel = ViewModelProviders.of(getActivity()).get(DemoViewModel.class); //使用getActivity()获得的ViewModel 作用域在Activity里和所有他创建碎片的里,意思是你在其他Fragment也获取相同内存地址的ViewModel

mViewModel = ViewModelProviders.of(this).get(DemoViewModel.class); //这个ViewModel是独立的,只为这个Fragment单独服务,其他Fragment无法获取到相同内存地址的ViewModel

 

end

推荐阅读