SkillAgentSearch skills...

MVVMSmart

基于谷歌最新AAC架构,MVVM设计模式的一套快速开发库,整合ViewModel+Lifecycles+Navigation+DataBinding+LiveData+Okhttp+Retrofit+RxJava+Glide等主流模块,满足日常开发需求。使用该框架可以快速开发高质量、易维护的Android应用。 项目组会持续维护,请放心使用.欢迎Start并Fork交流.

Install / Use

/learn @wzqjava/MVVMSmart

README

MVVMSmart-kotlin

目前,android基于MVVM模式开发框架比较少。MVVMSmart-kotlin是以谷歌Jetpack架构组件ViewModel+Lifecycles+Navigation+DataBinding+LiveData+Okhttp+Retrofit+RxJava+Glide等,加上各种原生控件自定义的BindingAdapter,让事件与数据源完美绑定的一款容易上瘾的实用性MVVM快速开发框架。告别findViewById(),告别setText(),告别setOnClickListener()...

技术讨QQ群:531944409

最新日志 v2.0:2020年6月9日

  1. 重构优化网络框架
  2. 全局的Loading封装,loading包含动画功能,rxjava封装调用
  3. 修改开源稳定的测试网络接口
  4. 添加TestNetFragment,方便开发者调试自己喜欢的任何接口
  5. 开发环境动态切换(dev,qa,release)+渠道管理+动态配置BaseUrl+企业级签名配置规范.

最新日志 v2.0:2020年4月28日

  1. 上线kotlin稳定版
  2. 增加recyclerview无数据的默认页,同时支持其他任何布局层次无数据的默认页,一行代码显示默认页
  3. 优化任何页面一行代码退出程序, AppManagerMVVM堆栈管理(2020.04.29)

中文文档

建议大家用clone的方式下载开源框架,方便及时更新,建议大家使用kotlin项目,毕竟是Android的第一语言,越用约开心。

  1. MVVMsmart地址: https://github.com/wzqjava/MVVMSmart (包含kotlin分支和java分支)
  2. 分支名称:MVVMSmart-kotlin(切换分支,readme会自动切换成对应语言)
  3. 分支名称:MVVMSmart-java(切换分支,readme会自动切换成对应语言)
  4. AndroidStudio 从github下载代码的正确姿势:https://juejin.im/post/5e09dd306fb9a01648718430
  5. MVVMSmart系列解读文章: https://juejin.im/user/574e36b179bc440062693484/posts

框架特点

  • 快速开发 只需要写项目的业务逻辑,不用去关心网络请求、权限申请、View的生命周期等问题,撸起袖子就是干,高效开发。

  • 维护方便 MVVM开发模式,低耦合,逻辑分明。Model层负责将请求的数据交给ViewModel;ViewModel层负责将请求到的数据做业务逻辑处理,最后交给View层去展示,与View一一对应;View层只负责界面绘制刷新,不处理业务逻辑,非常适合分配独立模块开发。

  • 本项目使用流行框架 google AAC(Android Architecture Components:安卓架构组件): ViewModel:负责管理UI的逻辑好数据, Lifecycles:负责处理数据和UI生命周期的自动管理 Navigation:google推荐的轻Activity方案,一个大的功能只用一个Activity,内部导航多个Fragment. DataBinding:负责ViewModel中数据和UI控件的自动绑定 [LiveData]:(https://developer.android.google.cn/jetpack)负责ViewModel中数据的管理和与UI层的通信 retrofit+okhttp rxJava负责网络请求 gson负责解析json数据 glide负责加载图片; BaseRecyclerViewAdapterHelper负责管理RecyclerView的适配器 rxpermissions负责Android 6.0权限申请 material-dialogs一个漂亮的、流畅的、可定制的material design风格的对话框。

  • 数据绑定

    满足google目前控件支持的databinding双向绑定,并扩展原控件一些不支持的数据绑定。例如将图片的url路径绑定到ImageView控件中,在BindingAdapter方法里面则使用Glide加载图片;View的OnClick事件在BindingAdapter中方法使用RxView防重复点击,再把事件回调到ViewModel层,实现xml与ViewModel之间数据和事件的绑定(框架里面部分扩展控件和回调命令使用的是@kelin原创的)。UI的事件儿绑定请在UI中处理,否则不好维护,可以在UI中触发,UI中持有viewmodel,调用viewmodel中的业务即可.

  • 基类封装

    专门针对MVVM模式打造的BaseActivityMVVM、BaseFragmentMVVM、BaseViewModelMVVM,在View层中不再需要定义ViewDataBinding和ViewModel,直接在BaseActivityMVVM、BaseFragmentMVVM上限定泛型即可使用.支持navigation导航Fragment的管理,导航返回时候回调用OnCreateView,BaseFragmentMVVM已经封装,标题使用include导入布局, Base层预留的有 initToolbar(),标题的返回、文字设置、右侧更多等在这个方法初始化即可,普通界面只需要编写Fragment,然后使用navigation导航,不用在manifest注册,性能也更好.

  • 全局操作

  1. google的AAC架构,ViewModel+Lifecycles+Navigation+DataBinding+LiveData。
  2. LoggingInterceptor全局拦截网络请求日志,打印Request和Response,格式化json、xml数据显示,方便与后台调试接口。
  3. 全局Cookie,支持SharedPreferences和内存两种管理模式。
  4. 通用的网络请求异常监听,根据不同的状态码或异常设置相应的message。
  5. 全局的异常捕获,程序发生异常时不会崩溃,可跳入异常界面重启应用。
  6. 全局唯一可信事件源处理,提供LiveEventBus回调方式。
  7. 全局任意位置一行代码实现文件下载进度监听(暂不支持多文件进度监听)。
  8. 任何布局层次无数据时候的默认页(主要用来: 列表无数据的默认页,接口error的默认页,无网络的默认页等,动态传入文字和图片的id即可)
  9. app崩溃重启功能(任意指定重启Activity即可,一般是欢迎页),debug模式崩溃后测试人员可以直接截屏崩溃日志给开发,再也不会听到测试说"又崩啦.."
  10. AppManagerMVVM管理类用两个栈管理Activity和Fragment,能动态获取栈顶UI,任何页面一行代码安全退出程序.
  11. 全局的Loading封装,loading包含动画功能,rxjava封装调用
  12. gradle企业级:签名配置+渠道配置+BaseUrl管理+ 打包apk命名区分环境管理
  13. 支持Arouter组件化
  14. 支持Post请求多参数封装成json提交
  15. 全局任何位置Toast功能,ViewModel中有许多toast需求使用很方便.
  16. 全局Tasks任务类管理,里面封装全局Handler,可以发送runnable到UIThread或普通Thread,都支持延迟发送,这个工具很实用.
  17. 生产环境都有token,封装自动请求token更新token,app长期不用token过期跳转登录页面(拦截器功能).
  18. 添加最小宽度适配方案, 目前全球主流适配方案.几乎适配所有手机.适配方案技术细节https://www.jianshu.com/p/1302ad5a4b04

1、准备工作

网上有很多MVVM入门资料,在此就不再阐述什么是MVVM了,不清楚的朋友可以先去了解一下。

  1. architecture-components-samples
  2. todo-mvvm-live
  3. MVVMHabit

1.1、启用databinding

在主工程app的build.gradle的android {}中加入:

dataBinding {
    enabled true
}

1.2、依赖Library

从远程依赖:

在根目录的build.gradle中加入

allprojects {
    repositories {
		...
        google()
        jcenter()
        maven { url 'https://jitpack.io' }
    }
}

在主项目app的build.gradle中依赖

下载例子程序,在主项目app的build.gradle中依赖例子程序中的mvvmsmart

dependencies {	
    ...
    api project(':mvvmsmart')// 这样导入方便看源码,也方便根据自己项目改造
}

1.3、配置config.gradle

下载例子程序,例子程序中的config.gradle放入你的主项目根目录中,然后在根目录build.gradle的第一行加入:

apply from: "config.gradle"

注意: config.gradle中的

android = [] 是你的开发相关版本配置,可自行修改,比如compileSdkVersion,buildToolsVersion,versionCode等等。

dependencies = [] 是依赖第三方库的配置,可以加新库,用户也可以自己修改版本号,目前都是androidx依赖.

1.4、配置AndroidManifest

添加权限:

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

配置Application:

自己的Application继承mvvmsmart中的BaseApplicationMVVM,或者调用

BaseApplication.setApplication(this);

来初始化你的Application

你可以在你的自己AppApplication中配置

//是否开启日志打印
KLog.init(true);
//配置全局异常崩溃操作
CaocConfig.Builder.create()
    .backgroundMode(CaocConfig.BACKGROUND_MODE_SILENT) //背景模式,开启沉浸式
    .enabled(true) //是否启动全局异常捕获
    .showErrorDetails(true) //是否显示错误详细信息
    .showRestartButton(true) //是否显示重启按钮
    .trackActivities(true) //是否跟踪Activity
    .minTimeBetweenCrashesMs(2000) //崩溃的间隔时间(毫秒)
    .errorDrawable(R.mipmap.ic_launcher) //错误图标
    .restartActivity(LoginActivity.class) //重新启动后的activity
    //.errorActivity(YourCustomErrorActivity.class) //崩溃后的错误activity
    //.eventListener(new YourCustomEventListener()) //崩溃后的错误监听
    .apply();

2、快速上手

2.1、第一个Fragment

为啥是第一Fragment,因为目前google IO 大会已经推荐在Activity中使用navigation来导航Fargment。目前sample中用Activity导航了所有功能Fragment,一个功能是一个Fargment.同时你想继续用一个个Activity也是可以的,ActivityBase层都已经处理好了. 以大家都熟悉的Recyclerview加载多条目为例:

  • 三个文件MultiRecycleViewFragment.javaMultiRecycleViewModel.javafragment_multi_rv.xml.xml
2.1.1、关联ViewModel

fragment_multi_rv.xml中关联LinearLayoutManager和MyMultiAdapter。

<layout>
    <data>
        <variable
            name="layoutManager"
            type="androidx.recyclerview.widget.LinearLayoutManager" />
        <variable
            name="adapter"
            type="com.wzq.sample.ui.recycler_multi.MyMultiAdapter" />
    </data>
    .....

</layout>

variable - type:类的全路径 <br>variable - name:变量名

2.1.2、继承BaseFragmentMVVM

MultiRecycleViewFragment继承BaseFragmentMVVM


class MultiRecycleViewFragment : BaseFragment<FragmentMultiRvBinding, MultiRecycleViewModel>() {
    private lateinit var mAdapter: MyMultiAdapter
    override fun initContentView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): Int {
        return R.layout.fragment_multi_rv
    }

    override fun initVariableId(): Int {
        return BR.viewModel
    }

    override fun initData() {
        super.initData()
        viewModel.data
        initRecyclerView()
    }

    override fun initViewObservable() {
        super.initViewObservable()
        viewModel.itemsEntityLiveData.observe(this, Observer { itemsEntities: ArrayList<ItemsEntity>? -> 		      			mAdapter.setNewData(itemsEntities) })
    }
    ....

fragment_multi_rv.xml后databinding会生成一个FragmentMultiRvBinding类。(如果没有生成,试着点击Build->Clean Project)

BaseFragmentMVVM是一个抽象类(专门在Sample中独立与框架处理,方便大家使用自己项目中的Base,不用修改自己项目中的base名称,框架中的Base都有MVVM后缀), base中有两个泛型参数,一个是ViewDataBinding,另一个是BaseViewModelMVVM,上面的ActivityLoginBinding则是继承的ViewDataBinding作为第一个泛型约束,MultiRecycleViewModel继承BaseFragmentMVVM作为第二个泛型约束。

重写BaseFragmentMVVM的两个抽象方法

initContentView() 返回界面layout的id<br> initVariableId() 返回viewModel变量的id,就像一个控件的id,可以使用R.id.xxx,这里的BR跟R文件一样,由系统生成,使用BR.xxx找到这个ViewModel的id。<br>

大家可以选择性重写initViewModel()方法,比如LoginViewModel中的重写.

@Override
public LoginViewModel initViewModel() {
    //View持有ViewModel的引用,如果没有特殊业务处理,这个方法可以不重写
    return ViewModelProviders.of(this).get(LoginViewModel.class);
}

注意: 一般都不用重写initViewModel(),默认会创建MultiRecycleViewFragment中第二个泛型约束的MultiRecycleViewModel,如果没有指定第二个泛型,则会创建BaseViewModelMVVM

2.1.3、继承BaseViewModelMVVM

MultiRecycleViewModel继承BaseViewModelMVVM

class MultiRecycleViewModel(application: Application) : BaseViewModel(application) {
    //给RecyclerView添加ObservableList
    var itemsEntityLiveData: MutableLiveData<ArrayList<ItemsEntity>> = MutableLiveData()
    fun getData() {
        val datas = ArrayList<ItemsEntity>()
        for (i in 0..49) {
            val itemBean = ItemsEntity(i, "MVVMSmart", TestUtils.getGirlImgUrl())
            if (i % 2 == 0) {
                itemBean.itemType = 0
            } else {
                itemBean.itemType = 1
            }
            datas.add(itemBean)
        }
        itemsEntityLiveData.value = datas

    }
}
    .....

BaseViewModelMVVM与BaseFragmentMVVM通过StateLiveData来处理常用UI逻辑,即可在ViewModel中使用父类的showDialog()、startActivity()等方法。在这个MultiRecycleViewModel中就可以尽情的写你的逻辑了!

BaseActivityMVVM的使用和BaseFragmentMVVM几乎一样(BaseFragmentMVVM中单独处理的配合navigation),详情参考Sample。

2.2、数据绑定

拥有databinding框架自带的双向绑定,配合LiveData使用,逻辑特别清晰

2.2.1、自定义ImageView图片加载

绑定图片路径:

在ViewModel中定义

public String imgUrl = "http://img0.imgtn.bdimg.com/it/u=2183314203,562241301&fm=26&gp=0.jpg";

在ImageView标签中

binding:url="@{viewModel.imgUrl}"

url是图片路径,这样绑定后,这个ImageView就会去显示这张图片,不限网络图片还是

Related Skills

View on GitHub
GitHub Stars483
CategoryDevelopment
Updated1mo ago
Forks92

Languages

Java

Security Score

85/100

Audited on Jan 31, 2026

No findings