Android 全新MVVM框架搭建

640?wx_fmt=gif

640?wx_fmt=jpeg

Linux编程 点击右侧关注,免费入门到精通! 640?wx_fmt=jpeg


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


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


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


秀一把我的LoginActivity


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


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


public class LoginViewModel extends BaseViewModel<ILoginViewILoginModelLoginActivityBriefnessorimplements 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 == nullreturn;
        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 Briefnessorextends 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 IBaseViewM extends IBaseModelB extends Briefnessorextends AbsViewModel<Vimplements 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<Timplements 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 IBaseViewModelimplements 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


 推荐↓↓↓ 

640?wx_fmt=png

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

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

640?wx_fmt=png万水千山总是情,点个 “ 好看” 行不行
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
搭建一个基于Android Java的MVVM框架,可以按照以下步骤进行: 1. 首先,创建一个项目并导入所需的库和依赖项。你可以使用Android Studio来创建一个新项目,并在build.gradle文件中添加必要的依赖项,例如ViewModel和LiveData库。 2. 接下来,创建一个Model类来管理数据。在MVVM架构中,Model负责处理数据业务逻辑,例如从网络或数据库中获取数据。你可以定义一个类来实现这些功能,并在需要时更新数据。 3. 然后,创建一个ViewModel类来管理和处理视图逻辑。ViewModel充当了Model和View之间的中间层,它展示数据给视图,并响应用户的操作。在ViewModel中,你可以定义一些可观察的LiveData对象来绑定到视图上,以确保数据的实时更新。 4. 接下来,创建一个View类来展示数据和处理用户界面。View类负责布局和呈现UI元素,例如按钮和文本框。你可以使用XML布局文件来定义视图的外观,并在Activity或Fragment中加载它。 5. 最后,将View和ViewModel连接起来。你可以在View中使用Data Binding将ViewModel与UI元素绑定在一起,以便在数据变化时自动更新视图。此外,你还可以使用LiveData观察ViewModel中的数据变化,并在变化时刷新UI。 总结起来,搭建一个基于Android Java的MVVM框架包括创建Model、ViewModel和View类,并将它们连接起来以实现数据和视图之间的双向绑定。通过使用ViewModel提供的LiveData对象和Data Binding,可以确保视图的实时更新,并实现解耦和可维护性。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值