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

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

秀一把我的LoginActivity@BindLayout(R.layout.activity_login)public class LoginActivity extends BaseActivity implements ILoginView {    @Override

protected ILoginViewModel createViewModel(LoginActivityBriefnessor briefnessor) {        return new LoginViewModel(this, briefnessor);

}

}

是不是超级简洁,点击事件呢?怎么不见了,再看一看ViewModelpublic class LoginViewModel extends BaseViewModel 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() 

Toast.makeText(context(), "账号不正确", Toast.LENGTH_SHORT).show();            return;

}        if (pswd.length() 

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"?>

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">

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="账号" />

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="密码" />

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$)" />

style="@style/text_childer"

android:text="返回码" />

android:id="@+id/tv_code"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

app:bind="$result.code$" />

style="@style/text_childer"

android:text="结果:" />

android:id="@+id/tv_msg"

android:layout_width="wrap_content"

android:layout_height="wrap_content"

app:bind="$result.msg$" />

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

同时在对应的Activity上绑定相应的布局文件,Briefness就能暂时他强大的功能了,它会自动生成[类名+Briefnessor]的类。public class LoginActivityBriefnessor implements Briefnessor {    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

下面说一说BaseActivitypublic abstract class BaseActivity 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,并实现了IBaseViewpublic interface IBaseView {    Context applicationContext();    Activity context();

}

BaseViewModel继承AbsViewmodel并实现IBaseViewModel,持有Briefnessor,View,Model。public abstract class BaseViewModel extends AbsViewModel 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 implements IBaseViewModel{    protected WeakReference mViewRef;    protected WeakReference mBriefnessorRef;    protected void attachView(T view) {

mViewRef = new WeakReference(view);

}    protected void attachBriefnessor(Briefnessor briefnessor) {

mBriefnessorRef = new WeakReference(briefnessor);

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

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

}    public boolean isViewAttached() {        return mViewRef != null && mViewRef.get() != null & mBriefnessorRef != null & 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 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();

}

}

作者:Android高级开发

链接:https://www.jianshu.com/p/ef99ff863650

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐