MvcBind-快,很快,非常快

334 阅读9分钟

MvcBind

介绍

MvcBind快速开发框架,基于mvc+databinding为基础制作的轻量级快速开发基础框架。目标只有一个:快!上手快,理解快,开发快,维护快。

软件架构

软件架构说明
  框架基于经典的MVC模式,这里为什么不用mvp或者是mvvm呢?后两者笔者也有大量项目实践,实际使用中发现,两者的开发速度都比较慢(较mvc),尤其是mvp,采用了接口解耦,开发中需要写更多的类,声明更多的接口方法,然后再去实现这些方法,开发效率不佳。当然,不可否认的是,就后期维护来说,mvp和mvvm确实优于传统mvc模式,当时这种优势仅存在于mvc写的不规范的情况下,实际上规范化的mvc模式代码,维护并不会比后两者差太多。而且,事实上严格意义上来说,大部分人初学安卓的写法,并不能算是mvc,为什么这么说呢,我们不妨来看看mvc的交互图:

那么很多人所谓的mvc又是如何写的呢?

public class TestActivity extends Activity {
    private TextView mTextView;
    @Override
    protected void onCreate (Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        mTextView = findViewById(R.id.tv_date);
        mTextView.setText(System.currentTimeMillis());
    }
}

  这里只是写个简单的示例,和上图对比可以发现,大部分人所谓的mvc连model模块类都没有,所有的视图、数据、逻辑代码全部堆叠在activity或者fragment中,那么后期维护困难就必然了。就简单来讲,安卓中的mvc也该是由布局(view)、activity(control)、数据类(model)这三者构成才对,事实上你如果这么写了,明显比上述代码更好维护。但是,仅仅这样还是不够的,因为安卓中的布局xml文件职能比较少,很多东西并没有办法在xml中完成,这就造成你不得不写在activity(control)中,这样就又会造成view与control的分工混乱了,那么,如何解决这一问题?
  MvcBind采用吸取mvp的模式核心思想,明确分工,写一个页面时包含三个模块,model(数据类)、control(activity或fragment)、view(布局xml+view类)。这里与传统mvc模式的区别在于view由xml和一个独立的view控制类组成,与mvp的区别在于MvcBind不加入接口解耦机制,mvc三者之间可以直接调用其他方的公共方法。mvp的接口解耦机制过于冗余,而且就效果来说主要还是看使用者的功力,再好的mvp框架到初学者手中也是写的一团糟,所以本库直接去掉了mvp中的接口解耦机制,而保留了mvp基本的模块解耦思想。同时,为了减少模板代码,引入了databinding机制,view类中不需要任何findview代码。
  简单的介绍就说到这里,下面说说MvcBind的快体现在哪里,首先,假如我们需要创建一个activity,使用本框架你只需要:

这两步之后你将会得到:

如图所示,只需要简单两步你就可以获得mvc三个类和一个布局文件,4个文件中的初始代码展示:

public class TestActivityControl extends BaseActivity<TestActivityModel, TestActivityView> {
    @Override
    public void init (Bundle savedInstanceState) {

    }
}
public class TestActivityModel extends BaseModel {
    @Override
    public void init (IControl control) {

    }
}
public class TestActivityView extends BaseView<ActivityTestBinding> {
    @Override
    public void init (IControl control) {
        mBind.setControl(control);
    }
}
<layout 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"
>
    <data>
        <variable name="control" type="com.xujl.fastlib.base.IControl"/>
    </data>
    <!-- -->
    <LinearLayout android:layout_width="match_parent"
                  android:layout_height="match_parent"
                  android:orientation="vertical">

    </LinearLayout>
</layout>

  仅仅两步你就可以开始写自己的业务代码,再也不用像写mvp一样去写那么多类和接口,上述功能的实现参考笔者的另一篇文章:As模板
  当然,你也大可不必关心上述功能如何实现的,因为本库已经给出模板,位于仓库/工具目录下,只需要复制到as对应目录重启即可,具体使用方法参考使用说明。

安装教程

项目地址:gitee.com/biyouji_adm…

使用说明

基础功能:
1.下载项目源码到本地
2. 配置你的项目根build.gradle文件(参考下载的源码)
3. 导入fastlib到你的项目,并添加为你项目的依赖module

附加功能:
1.activity/fragment模板
  模板位置:源码目录/工具/快速生成类模板
  具体使用说明参考文件夹下的word文档
2.快捷生成bind数据类
  什么是bind数据类?都知道dataBinding需要一个数据实体进行绑定,通常有两种方法,一种是使用ObservableField对字段进行包装,但是这种方法非常麻烦,而且我们的实体通常是来源于json,json解析肯定是无法支持ObservableField类型的,如下:

 public ObservableField<String> name = new ObservableField<>();

还有一种就是实体类继承BaseObservable类,并且需要绑定的字段需要做如下处理:

    private String name;
    @Bindable
    public String getName () {
        return name;
    }

    public void setName (String name) {
        this.name = name;
        notifyPropertyChanged(BR.name);
    }

  和第一种写法相比,可能也不便捷,但优势在于json解析出来就可以直接和view进行绑定了,不用再去set一次值。但是大量的字段,重复添加这些东西,还是很浪费时间的,这时候就轮到插件出场了。
  插件目录:源码/工具/DbSetter.jar
  插件安装方法自行百度,不是这里需要介绍的,插件的源码也在工具/DbSetter-master下,如果想对插件作出优化,可以自行修改
  插件使用:

  注意,插件不会自动生成继承BaseObservable类的代码,需要自己手动添加,在实体类中使用快捷键alt+insert(AS默认),弹窗菜单第一个就是了,接下来就和系统的setter、gettter自动生成使用是一致的,使用后你将直接得到:
有红色报错的话,可以rebuild一下,如果依然报错就无视掉就行了,不影响运行,这个算是AS自己的bug。

为什么快?

1.上手快
  为什么上手快?因为首先就使用了大家熟知的mvc模式,不需要太多额外的学习成本,本框架最大的学习成本应该是对数据绑定的理解,不过这个相比去吃透mvp、mvvm还是简单很多。
2.理解快
  框架源码简单,没有太多花里胡哨的东西,只要肯花个半天左右的时间来看,就能一目了然整体设计思路。
3.开发快
  基于模板创建activity/fragment和自动生成bind数据类的setter/getter,可以节省大量首次开发时间,千万不要小看这部分创建的时间,一个新项目一般30个activity,10个左右的fragment,如果根据框架创建activity相关类和布局预计5分钟的话一个项目光是写这些模板代码都要近200分钟左右,这么算是比较保守的了,实际时间可能还不止。

  如果你以为开发快仅仅是上面两点就大错特错了,上面不过是冰山一角,下面将详细说明,本库如何实现快速开发:
  无需再写布局id,下面的代码,估计大家在各种框架中经常见:

    @Override
    public int initContentView (Bundle savedInstanceState) {
        return R.layout.activity_card_goods_list;
    }

  当然,各种框架的方法名可能有一定出入,但是目的基本都是一样,子类传递布局id给base类进行布局加载,这么做无可厚非,但是写的多了,就很烦这种代码,如果你没有用模板自动生成就更烦,每新增一个页面就要花个2秒的时间写这种没营养的代码,那么本库中如何处理呢?

public class LoadingFragmentView extends BaseView<FragmentLoadingBinding> {
    @Override
    public void init (IControl control) {

    }
}

  你会发现没有返回任何布局id,但是运行时页面可以准确加载布局R.layout.fragment_loading,具体原理,这里不细说,有兴趣的直接去看源码,没有几行代码。总体来说这个功能的实现基于两点:

    1.标准化命名,mvc三个模块以及布局的命名有着严格要求,比如上面的LoadingFragmentView他对应的其他文件一定是LoadingFragmentControl、LoadingFragmentModel、R.layout.fragment_loading。当然你大可不必担心命名出错,因为,这些文件都是模板生成的。
    2.反射,有了标准化的命名,我们在基类就可以很容易的通过反射获取类名,再通过类名拼接成布局文件id,然后进行布局加载了!
  多种功能实例参考

  demo中提供了多种常见场景实例,并且进行了分类和提供了搜索,后续也会持续更新demo,让你成为无情的copy机器,只用关注自己的业务逻辑代码,这些没营养的代码统统写好,拿去黏贴一下就用。
  多种开发模式切换,你开心就好
  这里的多种模式是指:
    你不想用mvc,你说我的页面逻辑超级简单,就展示一个数据,生成3个类太傻了,我就想全部写在一个activity里?没问题!

public class ActivityModeFragmentControl extends BaseFragment {
    @Override
    public void init (Bundle savedInstanceState) {

    }
}

    页面设计太复杂,或者各种原因,不能或者不想使用databinding?没问题!

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="本页面没有使用dataBinding" />

</LinearLayout>
public class NoBindingFragmentView extends BaseView {
    @Override
    public LayoutBuilder configLayout () {
        return super.configLayout().setEnableDataBinding(false);
    }

    @Override
    public void init (IControl control) {

    }
}

    既不想不用binding也不想用mvc,只想用最简单的acivity/fragment?没问题!

public class SimpleModeFragmentControl extends BaseFragment {
    @Override
    protected BaseView createDefaultView () {
        return new BaseView() {
            @Override
            public void init (IControl control) {

            }

            @Override
            public LayoutBuilder configLayout () {
                return super.configLayout().setEnableDataBinding(false);
            }
        };
    }

    @Override
    public void init (Bundle savedInstanceState) {

    }

}

  当然了,以上是本库支持的模式,但是通常情况下非常不建议关闭databinding。

项目涉及的三方库(只罗列fastlib的依赖库)

  1. 线程池RxTask
  2. 刷新布局SmartRefreshLayout
  3. 消息总线eventbus
  4. BaseRecyclerViewAdapterHelper
  5. Rxjava
  6. retrofit
  7. logger
  8. fragmentation
  9. rxpermissions
  10. 调试工具doraemonkit
  11. 弹窗基类BasePopup

文档持续更新中。。。