一、首先使用ViewModel写一个小案例,之后在此基础上,结合LiveData一起使用。
1、创建TimerViewModel类
/** * @Author: ly * @Date: 2022/9/13 * @Description: 继承ViewModel类,将视图与数据分离 */ public class TimerViewModel extends ViewModel { private Timer timer; private int currentSecond; /** * 开始计时 */ public void startTiming() { if (timer == null) { currentSecond = 0; timer = new Timer(); TimerTask timerTask = new TimerTask() { @Override public void run() { currentSecond++; if (onTimeChangeListener != null) { onTimeChangeListener.onTimeChanged(currentSecond); } } }; timer.schedule(timerTask, 1000, 1000); } } /** * 通过接口的方式,完成对调用者的通知 * 实际上这种方式不是很好,更好的方式是通过LiveData组件来实现 */ public interface OnTimeChangeListener { void onTimeChanged(int second); } private OnTimeChangeListener onTimeChangeListener; public void setOnTimeChangeListener(OnTimeChangeListener onTimeChangeListener) { this.onTimeChangeListener = onTimeChangeListener; } @Override protected void onCleared() { super.onCleared(); timer.cancel(); } }
2、在MainActivity中,通过实现接口OnTimeChangeListener ,进行数据变化的监听。
public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); iniComponent(); } private void iniComponent() { final TextView textView = findViewById(R.id.textView); TimerViewModel timerViewModel = new ViewModelProvider(this).get(TimerViewModel.class); timerViewModel.setOnTimeChangeListener(new TimerViewModel.OnTimeChangeListener() { @Override public void onTimeChanged(int second) { //更新UI界面 runOnUiThread(new Runnable() { @Override public void run() { textView.setText(String.valueOf(second)); } }); } }); timerViewModel.startTiming(); } }
二、将上面的案例,结合LiveData组件一起使用,这样会更方便,减少代码的冗余。
1、首先介绍一下LiveData组件
LiveData是一个可被观察的数据容器类,具体来说,可以将LiveData理解为一个数据的容器,它将数据包装起来,使数据成为被观察者,当该数据发生变化的时候,观察者就能获得通知,我们不需要自己去实现观察者模式,LiveData内部已经默认实现好了,我们只要使用就可以了。
下面我们就用LiveData取代上面所定义的OnTimeChangeListener 接口,完成ViewModel与页面之间的通信。
1、TimerWithLiveDataViewModel 类如下
/** * @Author: ly * @Date: 2022/9/1 * @Description: LiveData是一个抽象类,不能直接使用,我们使用它的直接子类MutableLiveData */ public class TimerWithLiveDataViewModel extends ViewModel { //将currentSecond这个字段用MutableLiveData包装起来 private MutableLiveData<Integer> currentSecond; private Timer timer; private int second = 0; public LiveData<Integer> getCurrentSecond() { if (currentSecond == null) { currentSecond = new MutableLiveData<>(); } return currentSecond; } /** * 开始计时 */ public void startTiming() { if (timer == null) { timer = new Timer(); second = 0; TimerTask timerTask = new TimerTask() { @Override public void run() { currentSecond.postValue(second++); } }; timer.schedule(timerTask, 1000, 1000); } } @Override protected void onCleared() { super.onCleared(); timer.cancel(); } }
2、MainActivity类如下
public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); iniComponent(); } final TextView textView = findViewById(R.id.textView); final Button btn = findViewById(R.id.btn); TimerWithLiveDataViewModel timerWithLiveDataViewModel = new ViewModelProvider(this).get(TimerWithLiveDataViewModel.class); //得到ViewModel中的LiveData final MutableLiveData<Integer> liveData = (MutableLiveData<Integer>) timerWithLiveDataViewModel.getCurrentSecond(); //通过LiveData.observe()观察ViewModel中数据的变化 liveData.observe(this, new Observer<Integer>() { @Override public void onChanged(Integer integer) { //收到回调更新UI界面 textView.setText("Time:" + integer); } }); //重置计时器 btn.setOnClickListener((v) -> { //完成对ViewModel中数据的更新 //setValue(T) 必须在主线程中调用 , // 而 postValue(T) 既可以在主线程中调用, 也可以在子线程中调用 liveData.setValue(0); }); //计时开始 timerWithLiveDataViewModel.startTiming(); } }
以上是ViewModel和LiveData一起使用的最基本用法。