Linux编程 点击右侧关注,免费入门到精通!

来源丨安卓巴士Android开发者门户

闲话不多少,还是老套路,处理一个登陆的业务。详细的介绍MVVM我就不多说了,网上一大把,毕竟吹水还是我的弱项。

主要实现的功能有两个输入框,一个登陆按钮,两个TextView显示登陆结果。

秀一把我的LoginActivity

@BindLayout(R.layout.activity_login)public class LoginActivity extends BaseActivity<ILoginViewModel, LoginActivityBriefnessor> implements ILoginView {    @Override    protected ILoginViewModel createViewModel(LoginActivityBriefnessor briefnessor) {        return new LoginViewModel(this, briefnessor);    }}

是不是超级简洁,点击事件呢?怎么不见了,再看一看ViewModel

public class LoginViewModel extends BaseViewModel<ILoginView, ILoginModel, LoginActivityBriefnessor> implements ILoginViewModel {

    public LoginViewModel(ILoginView view, LoginActivityBriefnessor briefnessor) {        super(view, briefnessor);    }

    @Override    protected ILoginModel createModel() {        return new LoginModel(this);    }

    @Override    public void onLoginClick(String account, String pswd) {        if (account.length() < 3) {            Toast.makeText(context(), "账号不正确", Toast.LENGTH_SHORT).show();            return;        }        if (pswd.length() < 3) {            Toast.makeText(context(), "密码不正确", Toast.LENGTH_SHORT).show();            return;        }        model.login(account, pswd);    }

    @Override    public void callbackLogin(LoginResult result) {        briefnessor.setResult(result);    }}

ViewModel制作了登陆的数据验证,以及登陆回调的实现,model层完成模拟了登陆。

整个登陆的业务流程Activity并没有参与,在这其中就不得不提一个关键的中间件Briefness,它连接了View层与Model层,帮我们实现了数据绑定,以及事件传递。
我们先看一看布局是如何实现的

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:app="http://schemas.android.com/apk/res-auto"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:orientation="vertical"    app:imports="com.hacknife.demo.bean.LoginResult,result"a    app:viewModel="com.hacknife.demo.mvvm.viewmodel.ILoginViewModel"    tools:ignore="MissingPrefix">

    <EditText        android:id="@+id/et_account"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:layout_marginHorizontal="40dp"        android:layout_marginVertical="10dp"        android:hint="账号" />

    <EditText        android:id="@+id/et_pswd"        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:layout_marginHorizontal="40dp"        android:layout_marginVertical="10dp"        android:hint="密码" />

    <Button        android:id="@+id/btn_login"        android:layout_width="match_parent"        android:layout_height="40dp"        android:layout_marginHorizontal="40dp"        android:layout_marginVertical="10dp"        android:text="登陆"        app:transfer="onLoginClick($et_account$,$et_pswd$)" />

    <LinearLayout style="@style/text_parent" android:layout_marginHorizontal="40dp">

        <TextView            style="@style/text_childer"            android:text="返回码" />

        <TextView            android:id="@+id/tv_code"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            app:bind="$result.code$" />    </LinearLayout>

    <LinearLayout style="@style/text_parent" android:layout_marginHorizontal="40dp">

        <TextView            style="@style/text_childer"            android:text="结果:" />

        <TextView            android:id="@+id/tv_msg"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            app:bind="$result.msg$" />    </LinearLayout></LinearLayout>

布局中,根布局绑定了ViewModel,以及用于展示登陆结果的数据源。登陆按钮传递单击登陆事件,剩下的两个textView绑定相应的字段。

同时在对应的Activity上绑定相应的布局文件,Briefness就能暂时他强大的功能了,它会自动生成[类名+Briefnessor]的类。

public class LoginActivityBriefnessor implements Briefnessor<LoginActivity> {    public EditText et_account;    public EditText et_pswd;    public Button btn_login;    public TextView tv_code;    public TextView tv_msg;    public LoginResult result;    public ILoginViewModel viewModel;

    @Override    public void bind(final LoginActivity host, Object source) {        if (!Utils.contentViewExist(host)) {            host.setContentView(R.layout.activity_login);        }        et_account = (EditText) host.findViewById(R.id.et_account);        et_pswd = (EditText) host.findViewById(R.id.et_pswd);        btn_login = (Button) host.findViewById(R.id.btn_login);        tv_code = (TextView) host.findViewById(R.id.tv_code);        tv_msg = (TextView) host.findViewById(R.id.tv_msg);        btn_login.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                viewModel.onLoginClick(et_account.getText().toString().trim() , et_pswd.getText().toString().trim());            }        });

    }

    @Override    public void clear() {        this.result = null;        this.viewModel = null;    }

    @Override    public void clearAll() {        this.result = null;        this.viewModel = null;        this.et_account = null;        this.et_pswd = null;        this.btn_login = null;        this.tv_code = null;        this.tv_msg = null;    }    @Override    public void bindViewModel(Object viewModel) {        this.viewModel = (ILoginViewModel) viewModel;    }    public void setResult(LoginResult result) {        if (result == null) return;        this.result = result;        BriefnessInjector.injector(tv_code,result.getCode());        BriefnessInjector.injector(tv_msg,result.getMsg());    }}

该类实现了数据绑定,以及向ViewModel发送消息附带输入框中的值。

Briefness的具体用法,请参考

https://github.com/hacknife/briefness

下面说一说BaseActivity

public abstract class BaseActivity<T extends IBaseViewModel,B extends Briefnessor> extends AppCompatActivity implements IBaseView {    protected T viewModel;    protected B briefnessor;

    @Override    protected void onCreate(@Nullable Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        briefnessor = (B )Briefness.bind(this);        viewModel = createViewModel(briefnessor);        briefnessor.bindViewModel(viewModel);        initView();    }

    protected abstract T createViewModel(B briefnessor);

    @Override    protected void onDestroy() {        super.onDestroy();        if (viewModel != null)            viewModel.dettachView();    }

    protected void initView() {    }

    @Override    public Context applicationContext() {        return getApplication();    }

    @Override    public Activity context() {        return this;    }}

BaseActivity中初始化了Briefness并创建ViewModel绑定到Briefness,并实现了IBaseView

public interface IBaseView {

    Context applicationContext();

    Activity context();}

BaseViewModel继承AbsViewmodel并实现IBaseViewModel,持有Briefnessor,View,Model。

public abstract class BaseViewModel<V extends IBaseView, M extends IBaseModel, B extends Briefnessor> extends AbsViewModel<V> implements IBaseViewModel {

    protected V view;    protected M model;    protected B briefnessor;

    public BaseViewModel(V view, B briefnessor) {        this.attachView(view);        this.attachBriefnessor(briefnessor);        this.view = getView();        this.briefnessor = (B) getBriefnessor();        model = createModel();    }

    protected abstract M createModel();

    @Override    public Context applicationContext() {        return view.applicationContext();    }

    @Override    public Activity context() {        return view.context();    }}

AbsViewModel 的作用主要是释放相应的连接关系。

public abstract class AbsViewModel<T> implements IBaseViewModel{    protected WeakReference<T> mViewRef;    protected WeakReference<Briefnessor> mBriefnessorRef;

    protected void attachView(T view) {        mViewRef = new WeakReference<T>(view);    }

    protected void attachBriefnessor(Briefnessor briefnessor) {        mBriefnessorRef = new WeakReference<Briefnessor>(briefnessor);    }

    protected T getView() {        return mViewRef.get();    }

    protected Briefnessor getBriefnessor() {        return mBriefnessorRef.get();    }

    public boolean isViewAttached() {        return mViewRef != null &amp;&amp; mViewRef.get() != null &amp; mBriefnessorRef != null &amp; mBriefnessorRef.get() != null;    }

    public void dettachView() {        if (mViewRef != null) {            mViewRef.clear();            mViewRef = null;        }        if (mBriefnessorRef != null) {            mBriefnessorRef.clear();            mBriefnessorRef = null;        }    }}

BaseModel 持有ViewModel,并实现了IBaseView。

public abstract class BaseModel<VM extends IBaseViewModel> implements IBaseModel {    protected VM viewModel;

    public BaseModel(VM viewModel) {        this.viewModel = viewModel;    }

    @Override    public Context applicationContext() {        return viewModel.applicationContext();    }

    @Override    public Activity context() {        return viewModel.context();    }}

写的不好,请多多见谅,毕竟小学都没毕业

如果还有什么不明白的,代码直通车

https://github.com/hacknife/Briefness/tree/master/example/src/main/java/com/hacknife/demo/mvvm

 推荐↓↓↓ 

?16个技术公众号】都在这里!

涵盖:程序员大咖、源码共读、程序员共读、数据结构与算法、黑客技术和网络安全、大数据科技、编程前端、Java、Python、Web编程开发、Android、iOS开发、Linux、数据库研发、幽默程序员等。

万水千山总是情,点个 “ 好看” 行不行

Android 全新MVVM框架搭建相关推荐

  1. Android MVVM框架搭建(十)Hilt、ViewBinding、Activity Result API

    Android MVVM框架搭建(十)Hilt.ViewBinding.Activity Result API 前言 正文 一.依赖 二.Hilt使用 1. Hilt 应用类 2. ViewModel ...

  2. Android MVVM框架搭建(八)高德地图定位、天气查询、BottomSheetDialog

    Android MVVM框架搭建(八)高德地图定位.天气查询.BottomSheetDialog 前言 正文 一.集成SDK 二.基础配置 ① 权限配置 ② 配置Key 三.显示地图 ① MapFra ...

  3. Android MVVM框架搭建(三)MMKV + Room + RxJava2

    Android MVVM框架搭建(三)MMKV + Room + RxJava2 前言 正文 一.添加依赖 二.MMKV 1. 初始化 2. 数据存取 3. 使用 三.Room 1. @Entity ...

  4. Android MVVM框架搭建(二)OKHttp + Retrofit + RxJava

    Android MVVM框架搭建(二)Retrofit + RxJava 前言 正文 一.引入依赖 二.工具类 三.构建网络框架 1. Base 2. 异常处理 3. 拦截器 4. 网络请求服务 四. ...

  5. Android MVVM框架搭建(七)Permission、AlertDialog、拍照和相册选取

    Android MVVM框架搭建(七)Permission.AlertDialog.拍照和相册选取 前言 正文 一.数据库升级 二.数据操作 二.自定义Dialog ① DialogViewHelpe ...

  6. Android MVVM框架搭建(九)TabLayout、ViewPager、城市地图天气切换

    Android MVVM框架搭建(九)TabLayout.ViewPager.城市地图切换 前言 正文 一.父Fragment加载子Fragment ① Fragment适配器 ② TabLayout ...

  7. android mvvm框架搭建_轻松搭建基于JetPack组件的MVVM框架

    原文链接:轻松搭建基于JetPack组件的MVVM框架 - 掘金 Brick github gitee 介绍 辅助android开发者搭建基于JetPack组件构建MVVM框架的注解处理框架.通过注解 ...

  8. Android App软件框架搭建

    1. App软件框架搭建 1.0软件基本架构 1.1创建MainActivity并设置布局文件 布局文件如下: <?xml version="1.0" encoding=&q ...

  9. android 换肤框架搭建及使用 (3 完结篇)

    本系列计划3篇: Android 换肤之资源(Resources)加载(一) setContentView() / LayoutInflater源码分析(二) 换肤框架搭建(三) - 本篇 tips: ...

最新文章

  1. 月薪没到30K的程序员必须要背的面试八股文,我先啃为敬。。。
  2. python list add_用Python创建List对象类
  3. 【NLP】NLP 语义匹配:经典前沿方案整理
  4. 【搜索引擎基础知识1】搜索引擎基本架构
  5. LeetCode--171--Excel表列序号
  6. 容器中apscheduler不执行_APScheduler:定时任务框架
  7. 基于Android的聊天软件,Socket即时通信,实现用户在线聊天
  8. 软件测试基础课程学习笔记4--测试用例设计方法技巧
  9. C++复习 auto
  10. CString,string,char*之间的转换
  11. mysql 数据恢复 binlog
  12. YTU OJ 3229: 硬币组合
  13. Day2 Excel与数据处理之定位条件、选择性粘贴及查找功能
  14. No virtual method
  15. Golang FORM相关字段理解
  16. 怎样在网上赚钱啊,小编告诉你6种赚钱方式!
  17. 程序员幽默:让你笑到抽搐的自黑段子
  18. web项目经理手册-【7】项目经理需要铭记在心的话
  19. CFD冲蚀模拟的一些理论
  20. 使用ARCHPR进行zip明文攻击

热门文章

  1. Linux阅码场 - Linux内核月报(2020年08月)
  2. matlab树莓派usb摄像头,求 问Simulink做树莓派摄像头显示的一些问题
  3. 洛谷P1055 ISBN 号码 —— JAVA
  4. 便携式移动打印协议CPCL介绍
  5. 《我的第一本C++书》迷你书——看图学C++免费下载
  6. 【MySQL】Python3 MySQL数据库的基本操作
  7. springCloud-OAuth2 客户端,用户认证源码分析
  8. java int 保留两位小数_java 保留两位小数的几种方法
  9. 5G赋能智慧城市白皮书 附下载地址
  10. 小米手机1999元叫板iPhone