• Android ViewModel与LiveData组件组合使用详解


    博主前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住也分享一下给大家,
    👉点击跳转到网站

    一、首先使用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();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49

    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();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    二、将上面的案例,结合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();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42

    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();
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    以上是ViewModel和LiveData一起使用的最基本用法。

  • 相关阅读:
    官网安装Python包太慢?教你三种Pytorch的下载安装方式,保证你再也不用出现Error
    第3章 列表简介
    LQ0139 油漆面积【枚举】
    分布式文件系统对比与选型参考
    板凳--------第60章 SOCKET:服务器设计
    Ruby教程_编程入门自学教程_菜鸟教程-免费教程分享
    [java]深度剖析面向对象编程
    SpringBoot Actuator监控组件笔记
    数字藏品市场“三大套路”
    程序验证Jackson反序列化的规则、Jackson序列化与反序列化关键方法程序详细分析
  • 原文地址:https://blog.csdn.net/lu202032/article/details/126842524