• 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一起使用的最基本用法。

  • 相关阅读:
    怎么实现在微信公众号点外卖的功能
    jdk和cglib动态代理
    数据丢失恢复怎么操作好?五种方法帮您恢复数据
    解决Adobe Premiere Pro CC 2018打开无反应,并出现.crash的文件问题
    Kata3.0.0 x LifseaOS x 龙蜥内核三管齐下!带你体验最新的安全容器之旅
    「go查漏补缺」命名规则以及 GROM 结构体的应用
    acwing 826. 单链表 学习笔记
    让我踩坑的超链接href属性
    await 关键字在 async 函数中确实表现出“等待”的效果,那异步的含义呢,异步指整个不影响主进程
    ospf多区域原理和配置
  • 原文地址:https://blog.csdn.net/lu202032/article/details/126842524