Android——超简单GT_MVVM入门系列-上篇

侵入式的 GT架构,请参考中篇:

【精选】Android——超简单GT_MVVM 深究系列-中篇_android gt-CSDN博客文章浏览阅读1.1k次。GT架构-用的是 GT_MVVM 架构模式_android gthttps://blog.csdn.net/qq_39799899/article/details/127093032?spm=1001.2014.3001.5501

前言:

相信不少伙伴在进行Android开发的时候,肯定遇见过 Activity 代码上千行的,这种代码非常难以维护,牵一发而动全身,像极了某印#国的电线杆的电线一样,网上调侃程序员修水管,越修水越多估计也是这么来的。

而框架意在将这Activity中上千行代码进行功能分类,并提高相同功能的重复使用率,我们大体可将功能简单分为三种 界面代码、业务代码、逻辑代码。让各自专一的完成各自任务。

 MVVM模式:

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAUGxheWZ1bEtpbmc=,size_20,color_FFFFFF,t_70,g_se,x_16

 (先解释一下箭头)

View ↔ ViewModel表示:View与ViewModel相互绑定,然后ViewModel与Model又相互持有彼此引用,相互持有引用相信大家已经非常熟悉了,但这相互绑定是怎样的,没了解过的伙伴估计不太理解。

相互绑定的话,View可以通过 ViewModel 从 Model 中获取数据;当获取到了数据之后,会通过自动绑定相互绑定的作用,设置到View界面展示。

相互绑定的作用:可以省去 组件获取、事件注册、数据获取、数据更新这些代码。我们来看看之前MVP中Activity代码,除去Presenter代码Model代码,View代码里剩下的全是组件获取、事件注册、数据获取、数据更新了,而MVVM就是省去这些代码。

  在使用GT库里封装的架构当然需要先依赖好GT库:

详细依赖教程请参看

GitHub - 1079374315/GTContribute to 1079374315/GT development by creating an account on GitHub.icon-default.png?t=N7T8https://github.com/1079374315/GT

本次来讲一下怎么使用GT库中封装好的架构来实现搭建简易的MVVM,咋们通过一个例子来讲解

实现效果图:

实现一个简单的添加词条到数据库的功能

咋们先来看看文件结构:

 主要目录是 Model View ViewModel 这三个目录

Model目录:写与数据处理有关的

View目录:写与View页面初始化有关的

ViewModel目录:写与业务逻辑有关的

 我们最后来看看去掉所有业务逻辑后的 纯 GT_MVVM 架构代码:

GT_MVVM 架构代码

Model 类

/**
 * @Description:负责数据(网络请求/数据库)逻辑处理
 */
public class Model<T> extends GT.Frame.GT_Model<T> {
    public Model(){
    }
}

View 类

@GT_DataBinding(setLayout = "activity_main",setBindingType = GT_DataBinding.Activity)
@GT.Annotations.GT_AnnotationActivity(R.layout.activity_main)
public class MainActivity extends MainActivityBinding<MainViewModel> {

    @Override
    protected void initView(Bundle savedInstanceState) {
        super.initView(savedInstanceState);
        GT.logt("持有 ViewModel 引用:" + viewModel);
    }

}

 不理解自动产生 Binding 类 的同学们可以点击这里去查看自动产生类使用教程

ViewModel 类

/**
 * @Description:负责业务逻辑处理
 */
public class MainViewModel extends GT.Frame.GT_BindingViewModel<MainActivity, Model<?>> {

    @Override
    protected void initView() {
        super.initView();
        GT.logt("持有 View 引用:" + bindingView);
        GT.logt("持有 Model 引用:" + bindingModel);
    }

}

这是结合了GT库内部注解后再加载GT库MVVM的代码

使用起来也是非常方便的

如果不使用 GT库自带的注解工具,不继承自动生成的 Binding类 来实现MVVM该怎么实现呢

Model 类

/**
 * @Description:负责数据(网络请求/数据库)逻辑处理
 */
public class Model<T> extends GT.Frame.GT_Model<T> {
    public Model(){
    }
}

View 类

//必要的,用于生成 MainActivityBinding
@GT_DataBinding(setLayout = "activity_main",setBindingType = GT_DataBinding.Activity)
public class MainActivity extends AppCompatActivity {

    private MainViewModel viewModel;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //构建 ViewModel
        MainActivityBinding<?> bindingView = GT.DataBindingUtil.setContentView(this);
        viewModel = new MainViewModel(bindingView);
        GT.logt("持有 ViewModel 引用:" + viewModel);
    }

}

 不理解自动产生 Binding 类 的同学们可以点击这里去查看自动产生类使用教程

ViewModel 类

/**
 * @Description:负责业务逻辑处理
 */
public class MainViewModel extends GT.Frame.MVVM_ViewModel<Model<?>> {

    private MainActivityBinding<?> binding;
    private Model<?> model;

    public MainViewModel(MainActivityBinding<?> binding) {
        this.binding = binding;
        //构建Model
        model = new Model<>();
        setBindingView(model);
        initView();
    }

    @Override
    protected void initView() {
        GT.logt("持有 View 引用:" + binding);
        GT.logt("持有 Model 引用:" + model);
    }

}

这样架构就搭好了,接下来我们来看看架构搭好了,具体是怎么实用的

我们先看看Model 目录里的:

Model

一个实体类, Hibernate 是GT库里封装好的数据库管理类(与MVVM无关),用于简易生成与使用数据库的

@GT.Hibernate.GT_Bean//标识待扫描入数据库的表
public class DemoBean {

    @GT.Hibernate.GT_Key
    private int ID;//定义主键

    private String time;    //时间
    private String value;   //词条

    public int getID() {
        return ID;
    }

    public String getTime() {
        return time;
    }

    public void setTime(String time) {
        this.time = time;
    }

    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
    }

    @Override
    public String toString() {
        return "DemoBean{" +
                "ID=" + ID +
                ", time='" + time + '\'' +
                ", value='" + value + '\'' +
                '}';
    }
}

一个Model 类,用于处理数据逻辑的类

/**
 * @Description:负责数据(网络请求/数据库)逻辑处理
 */
public class Model<T> extends GT.Frame.GT_Model<T> {

    //数据库管理对象
    private GT.Hibernate hibernate;

    public void setHibernate(GT.Hibernate hibernate) {
        this.hibernate = hibernate;
    }

    //添加一条数据
    public boolean add(String value) {
        DemoBean demoBean = new DemoBean();
        demoBean.setValue(value.length() == 0 ? "空白" : value);
        demoBean.setTime(GT.GT_Date.getDateTime_CH());
        return hibernate.save(demoBean)//保存该实体类
                .isStatus();//返回本次操作状态
    }

    //删除一条数据
    public boolean delete(int id) {
        return hibernate.delete(DemoBean.class, id)//删除单条数据
                .isStatus();//返回本次操作状态
    }

    //清空所有数据
    public boolean clearAll() {
        return hibernate.deleteAll(DemoBean.class)//删除所有数据
                .isStatus();//返回本次操作状态
    }

    //查询所有数据
    public List<DemoBean> queryAll() {
        return hibernate.flashback("ID")//按照ID倒序
                .queryAll(DemoBean.class);//查询返回
    }

}

Model 类这些,可以看出Model类仅仅处理与数据挂钩,接下来我们来看看 View 目录

MainActivity类,主页面

@GT_DataBinding(setLayout = "activity_main", setBindingType = GT_DataBinding.Activity)
@GT.Annotations.GT_AnnotationActivity(R.layout.activity_main)
public class MainActivity extends MainActivityBinding<MainViewModel> {

    @GT.Hibernate.Build
    private GT.Hibernate hibernate;//构建数据库对象

    @Override
    protected void initView(Bundle savedInstanceState) {
        super.initView(savedInstanceState);
        viewModel.setHibernate(hibernate);//将数据库对象给到 ViewModel 处理
    }

    //注册 单击事件
    @GT.Annotations.GT_Click({R.id.btn_add,R.id.btn_clear})
    public void onClick(View view) {
        viewModel.onClick(view);//将单击事件交给 ViewModel处理
    }

}

MainActivity 对应的布局文件:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <EditText
        android:id="@+id/et_data"
        android:layout_width="250dp"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:hint="输入词库"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_bias="0.496"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintVertical_bias="0.05" />

    <Button
        android:id="@+id/btn_add"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="10dp"
        android:text="添加"
        app:layout_constraintEnd_toStartOf="@+id/btn_clear"
        app:layout_constraintStart_toStartOf="@+id/et_data"
        app:layout_constraintTop_toBottomOf="@+id/et_data" />

    <Button
        android:id="@+id/btn_clear"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="10dp"
        android:text="清空"
        app:layout_constraintEnd_toEndOf="@+id/et_data"
        app:layout_constraintStart_toEndOf="@+id/btn_add"
        app:layout_constraintTop_toBottomOf="@+id/et_data"
        />

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/rv"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_marginTop="10dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/btn_add" />

</androidx.constraintlayout.widget.ConstraintLayout>

MainActivity继承了GT自动产生的 MainActivityBinding 类, 做了构建数据库并将对象传递给 Model 去管理,不理解自动产生 Binding 类 的同学们可以点击这里去查看自动产生类使用教程

DemoAdapter类,适配器页面

/**
 * @Description: 继承使用GT生成的 AdapterBinding ,也可使用其他方式生成的适配器进行搭配
 */

@GT_DataBinding(setLayout = "item_demo", setBindingType = GT_DataBinding.Adapter)
@GT.Annotations.GT_AnnotationAdapter(R.layout.item_demo)
public class DemoAdapter extends DemoAdapterBinding<DemoBean> {

    public OnAdapterClick onAdapterClick;

    public DemoAdapter(Context context, OnAdapterClick onAdapterClick) {
        super(context);
        this.onAdapterClick = onAdapterClick;
    }

    @Override
    protected void initView(DemoAdapterViewHolder holder, View itemView, int position, DemoBean demoBean) {
        super.initView(holder, itemView, position, demoBean);
        holder.tv_1.setText(demoBean.getID() + " 号");
        holder.tv_2.setText(demoBean.getValue());
        holder.tv_3.setText(demoBean.getTime());

        //单击加载
        itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                onAdapterClick.onClick(demoBean);
            }
        });

        //长按操作
        itemView.setOnLongClickListener(new View.OnLongClickListener() {
            @Override
            public boolean onLongClick(View view) {
                onAdapterClick.onLongClick(demoBean);
                return true;
            }
        });

    }

    //添加一个单击与长按后 传递实体类 给 ViewModel处理 的演示
    public interface OnAdapterClick {
        void onClick(DemoBean demoBean);
        void onLongClick(DemoBean demoBean);
    }

}

DemoAdapter 对应的布局文件:

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="#07B2FF"
    android:gravity="center"
    android:layout_margin="5dp"
    android:orientation="horizontal">

    <TextView
        android:id="@+id/tv_1"
        android:layout_weight="1"
        android:gravity="center"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="序列:"
        android:textColor="#FFFFFF"
        android:textSize="20sp" />

    <TextView
        android:id="@+id/tv_2"
        android:layout_weight="1"
        android:gravity="center"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="词语"
        android:textColor="#FFFFFF"
        android:textSize="20sp" />

    <TextView
        android:id="@+id/tv_3"
        android:layout_weight="1"
        android:gravity="center"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="时间"
        android:textColor="#FFFFFF"
        android:textSize="20sp" />

</LinearLayout>

适配器也使用了 继承使用GT生成的 AdapterBinding ,也可使用其他方式生成的适配器进行搭配

最后我们来看看 ViewModel 怎么进行联合的

/**
 * @Description:负责业务逻辑处理
 */
public class MainViewModel 
        extends GT.Frame.GT_BindingViewModel<MainActivity, Model<?>>
        implements DemoAdapter.OnAdapterClick {

    private DemoAdapter demoAdapter;//适配器

    @Override
    protected void initView() {
        super.initView();
        //初始化并
        demoAdapter = new DemoAdapter(bindingView, this);
        //设置适配器显示为垂直布局
        demoAdapter.setLinearLayoutManager_V(bindingView.rv);
    }

    //处理单击事件
    public void onClick(View view) {
        switch (view.getId()) {
            case R.id.btn_add:
                //保存数据,若 保存成功 则 刷新数据
                if (bindingModel.add(bindingView.et_data.getText().toString())) {
                    demoAdapter.setBeanList(bindingModel.queryAll());//刷新数据
                    GT.toast_s(bindingView, "添加成功");
                }
                break;
            case R.id.btn_clear:
                //清空数据,若 清空成功 则 刷新数据
                if (bindingModel.clearAll()) {
                    demoAdapter.setBeanList(bindingModel.queryAll());//刷新数据
                    GT.toast_s(bindingView, "清空成功");
                }
                break;
        }
    }

    @Override
    public void onClick(DemoBean demoBean) {
        GT.logt("来自适配器 item 的单击:" + demoBean);
    }

    @Override
    public void onLongClick(DemoBean demoBean) {
        GT.logt("来自适配器 item 的长按:" + demoBean);
        //使用GT库自带的 对话框
        new GT.GT_Dialog.GT_AlertDialog(bindingView)
                .dialogTwoButton(R.drawable.ic_launcher_background,
                        "长按提示", "是否删除该条数据?",
                        true, "确定", (dialogInterface, i) -> {
                            if (bindingModel.delete(demoBean.getID())) {
                                demoAdapter.setBeanList(bindingModel.queryAll());//刷新数据
                                GT.toast_s(bindingView, "删除成功");
                            }
                        }, "取消", (dialogInterface, i) -> {

                        }).show();
    }

    //将数据库对象给到 Model 管理
    public void setHibernate(GT.Hibernate hibernate) {
        bindingModel.setHibernate(hibernate);//这里赋值后 Model 里的 hibernate 才能工作
        demoAdapter.setBeanList(bindingModel.queryAll());//加载数据
    }

}

这就是所有的MVVM架构使用的代码了,当然,GT_MVVM目前支持绑定的页面有这些:

GT_DataBinding.Activity;
GT_DataBinding.Fragment;
GT_DataBinding.DialogFragment;
GT_DataBinding.Adapter;
GT_DataBinding.FloatingWindow;
GT_DataBinding.PopupWindow;
GT_DataBinding.View;

下面这是本次教程的Demo源码,里面有上面各种页面绑定MVVM的具体使用案例:

本章源码地址

GitHub - 1079374315/GT_MVVMDemo: GT_MVVM 演示源码GT_MVVM 演示源码. Contribute to 1079374315/GT_MVVMDemo development by creating an account on GitHub.icon-default.png?t=N7T8https://github.com/1079374315/GT_MVVMDemo

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

PlayfulKing

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值