• Android中级——MVVM


    MVVM是什么?

    Model-View-ViewMode架构,可看作MVP改进版,将此前Presenter的逻辑操作交给ViewMode中的Binder去处理

    在这里插入图片描述

    • Mode:封装数据存储及相关操作逻辑,与MVC/MVP不同的是会提供一系列实体类与UI绑定,ViewModel修改这些数据后将数据变化告诉View
    • View:处理界面逻辑但不参与业务逻辑,显示ViewModel提供的数据
    • ViewModel:视图模型与视图状态的合称,为View提供一个可供显示的数据模型并收集、处理这些数据,内部的Binder用于双向绑定,还可包含多个Child ViewModel

    MVVM实现

    前提

    在build.gradle中android节点添加如下代码(最低SDK版本为API7,Gradle版本为1.5.0-alpha1)

    dataBinding{
        enabled = true
    }
    
    • 1
    • 2
    • 3

    Model

    创建数据实体类LoginInfo

    • 继承BaseObservable
    • getXXX()方法通过@Bindable注解表示该方法所返回的数据被修改时会更新UI
    • setXXX()方法调用notifyPropertyChanged()告诉DataBinding该字段被更改
    public class LoginInfo extends BaseObservable {
        private String mUser;
        private String mPassword;
    
        public LoginInfo(String user, String password) {
            mUser = user;
            mPassword = password;
        }
    
        @Bindable
        public String getUser() {
            return mUser;
        }
    
        public void setUser(String user) {
            mUser = user;
            notifyPropertyChanged(BR.user);
        }
    
        @Bindable
        public String getPassword() {
            return mPassword;
        }
    
        public void setPassword(String password) {
            mPassword = password;
            notifyPropertyChanged(BR.password);
        }
    }
    
    • 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

    ViewModel

    LoginModel封装维护LoginInfo、点击事件、文本改变事件

    public class LoginModel {
        private static final String DEF_USER = "song";
        private static final String DEF_PASSWORD = "123";
        public LoginInfo mInfo;
        private OnLoginListener mListener;
    
        public LoginModel(OnLoginListener listener) {
            mListener = listener;
            mInfo = new LoginInfo("", "");
        }
    
        public TextWatcher getUserTextWatcher() {
            return new TextWatcher() {
                @Override
                public void beforeTextChanged(CharSequence s, int start, int count, int after) {
    
                }
    
                @Override
                public void onTextChanged(CharSequence s, int start, int before, int count) {
    
                }
    
                @Override
                public void afterTextChanged(Editable s) {
                    mInfo.setUser(s.toString());
                }
            };
        }
    
        public TextWatcher getPasswordTextWatcher() {
            return new TextWatcher() {
                @Override
                public void beforeTextChanged(CharSequence s, int start, int count, int after) {
    
                }
    
                @Override
                public void onTextChanged(CharSequence s, int start, int before, int count) {
    
                }
    
                @Override
                public void afterTextChanged(Editable s) {
                    mInfo.setPassword(s.toString());
                }
            };
        }
    
        public interface OnLoginListener {
            void onLoginSuccess();
    
            void onLoginFail();
        }
    
        public void onLoginClick(View view) {
            if (mInfo.getUser().equals(DEF_USER) && mInfo.getPassword().equals(DEF_PASSWORD)) {
                mListener.onLoginSuccess();
            } else {
                mListener.onLoginFail();
            }
        }
    }
    
    • 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
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63

    View

    xml文件根节点变为layout,布局分为

    • 数据部分:声明所使用到的数据实体类以及构造该对象时的引用名
    • UI部分:常规控件,可直接使用数据实体类对象中的字段、方法
    
    
    
        
    
            
        
    
        
    
            
    
            
    
            

    MainActivity开启线程3秒后修改数据会显示在UI

    • 通过DataBindingUtil.setContentView设置布局,布局名字为R.layout.ab_cd,则对应类为AbCdBinding,为其设置Model
    public class MainActivity extends AppCompatActivity implements LoginModel.OnLoginListener {
        private static final String TAG = "MainActivity";
        
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
            LoginModel model = new LoginModel(this);
            binding.setModel(model);
            new Thread(new Runnable() {
                @Override
                public void run() {
                    SystemClock.sleep(3000);
                    model.mInfo.setUser("New User");
                    model.mInfo.setPassword("New Password");
                }
            }).start();
        }
        
        @Override
        public void onLoginSuccess() {
            Log.d(TAG, "onLoginSuccess: ");
        }
        
        @Override
        public void onLoginFail() {
            Log.d(TAG, "onLoginFail: ");
        }
    }
    
    • 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
  • 相关阅读:
    Java中this关键字的常见用法
    Window环境搭建MySQL主从复制
    三个练手的软件测试实战项目(附全套视频跟源码)偷偷卷死他们
    【hive基础】hive常见操作速查
    【Vuex】vue状态机详解
    Leo赠书活动-05期 【打造敏捷测试团队】文末送书5本
    车牌识别平台开源(支持蓝牌、绿牌,准确率高达96%)
    C++的命名空间namespace详解及特殊情况分析
    【数学建模】MATLAB应用实战系列(八十八)-组合权重法应用案例(附MATLAB和Python代码)
    LeetCode 斐波那契序列
  • 原文地址:https://blog.csdn.net/qq_35258036/article/details/133932697