-
简单demo
效果:点击按钮,数字加一
控件:一个TestView,一个Button。
-
具体实现
activity_main.xml
<TextView
android:id="@+id/textview"
android:layout_width="match_parent"
android:layout_height="1px"
android:layout_weight="1"
android:textColor="#000000"
android:gravity="center"
android:textSize="50dp"/>
<Button
android:id="@+id/button"
android:layout_width="1px"
android:layout_height="match_parent"
android:layout_weight="1"
android:text="+1"
android:textSize="50dp"
android:textColor="#000000"/>
MyViewModel (这里只定义一个简单的变量number)
public class MyViewModel extends ViewModel {
public int number = 0;
}
MainActivity
public class MainActivity extends FragmentActivity{
private MyViewModel myViewModel;
private TextView textView;
private Button button;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
}
private void initView(){
myViewModel = new ViewModelProvider(this,new ViewModelProvider.NewInstanceFactory()).get(MyViewModel.class); //绑定ViewModel
textView = findViewById(R.id.textview);
textView.setText(String.valueOf(myViewModel.number));// Activity重新创建时保存number值
button = findViewById(R.id.button1);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
myViewModel.number++;
textView.setText(String.valueOf(myViewModel.number));
}
});
}
}
-
详细介绍
1. ViewModel的生命周期
上图是官网给的生命周期图,我们可以知道ViewModel存在于Activity各种生命周期。这样我们就不用担心Activity被destory、重新create时、或者旋转时,数据被销毁。比如上面的demo,旋转屏幕时,ViewModel不会重新创建,我们可以直接获取number的值。
2.优化使用(在Fragment之间共享数据)
Activity中两个或多个Fragment之间需要通信是很常见的。这些Fragment可以使用同一个Activity作用范围下的ViewModel来处理通信。
public class TestViewModel extends ViewModel {
private final MutableLiveData<String> data = new MutableLiveData<>();
public void setData(String s){
data.setValue(s);
}
public MutableLiveData<String> getData(){
return data;
}
}
public class AFragment extends Fragment {
private TestViewModel model;
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_a, null);
model = new ViewModelProvider(getActivity(),new ViewModelProvider.NewInstanceFactory()).get(TestViewModel.class);
model.setData("a");
return v;
}
}
public class BFragment extends Fragment {
private TestViewModel model;
private TextView textView;
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_b, null);
textView = v.findViewById(R.id.txt_b);
model = new ViewModelProvider(getActivity(),new ViewModelProvider.NewInstanceFactory()).get(TestViewModel.class);
model.getData().observe(getActivity(), new Observer<String>() {
@Override
public void onChanged(String s) {
textView.setText(s);
}
});
return v;
}
}
注意这两个Fragment在使用ViewModelProvider获取ViewModel时是用的getActivity()。因此,这两个Fragment都会收到相同的TestViewModel 实例,这个实例作用域是Activity。
这种方法提供了以下好处:
这个Activity不需要做任何事情,也不需要了解有关此通信的任何信息;
Fragment之间不需要了解彼此,除了TestViewModel 的联系。如果一个fragment消失了,其他fragment还可以继续正常工作;每个Fragment都有其自己的生命周期,并且不受其他生命周期的影响。如果一个Fragment替换另一个Fragment,UI将继续工作而不会出现任何问题。
网友评论