MVVMSmart
基于谷歌最新AAC架构,MVVM设计模式的一套快速开发库,整合ViewModel+Lifecycles+Navigation+DataBinding+LiveData+Okhttp+Retrofit+RxJava+Glide等主流模块,满足日常开发需求。使用该框架可以快速开发高质量、易维护的Android应用。 项目组会持续维护,请放心使用.欢迎Start并Fork交流.
Install / Use
/learn @wzqjava/MVVMSmartREADME
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日
- 重构优化网络框架
- 全局的Loading封装,loading包含动画功能,rxjava封装调用
- 修改开源稳定的测试网络接口
- 添加TestNetFragment,方便开发者调试自己喜欢的任何接口
- 开发环境动态切换(dev,qa,release)+渠道管理+动态配置BaseUrl+企业级签名配置规范.
最新日志 v2.0:2020年4月28日
- 上线kotlin稳定版
- 增加recyclerview无数据的默认页,同时支持其他任何布局层次无数据的默认页,一行代码显示默认页
- 优化任何页面一行代码退出程序, AppManagerMVVM堆栈管理(2020.04.29)
中文文档
建议大家用clone的方式下载开源框架,方便及时更新,建议大家使用kotlin项目,毕竟是Android的第一语言,越用约开心。
- MVVMsmart地址: https://github.com/wzqjava/MVVMSmart (包含kotlin分支和java分支)
- 分支名称:MVVMSmart-kotlin(切换分支,readme会自动切换成对应语言)
- 分支名称:MVVMSmart-java(切换分支,readme会自动切换成对应语言)
- AndroidStudio 从github下载代码的正确姿势:https://juejin.im/post/5e09dd306fb9a01648718430
- 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注册,性能也更好.
-
全局操作
- google的AAC架构,ViewModel+Lifecycles+Navigation+DataBinding+LiveData。
- LoggingInterceptor全局拦截网络请求日志,打印Request和Response,格式化json、xml数据显示,方便与后台调试接口。
- 全局Cookie,支持SharedPreferences和内存两种管理模式。
- 通用的网络请求异常监听,根据不同的状态码或异常设置相应的message。
- 全局的异常捕获,程序发生异常时不会崩溃,可跳入异常界面重启应用。
- 全局唯一可信事件源处理,提供LiveEventBus回调方式。
- 全局任意位置一行代码实现文件下载进度监听(暂不支持多文件进度监听)。
- 任何布局层次无数据时候的默认页(主要用来: 列表无数据的默认页,接口error的默认页,无网络的默认页等,动态传入文字和图片的id即可)
- app崩溃重启功能(任意指定重启Activity即可,一般是欢迎页),debug模式崩溃后测试人员可以直接截屏崩溃日志给开发,再也不会听到测试说"又崩啦.."
- AppManagerMVVM管理类用两个栈管理Activity和Fragment,能动态获取栈顶UI,任何页面一行代码安全退出程序.
- 全局的Loading封装,loading包含动画功能,rxjava封装调用
- gradle企业级:签名配置+渠道配置+BaseUrl管理+ 打包apk命名区分环境管理
- 支持Arouter组件化
- 支持Post请求多参数封装成json提交
- 全局任何位置Toast功能,ViewModel中有许多toast需求使用很方便.
- 全局Tasks任务类管理,里面封装全局Handler,可以发送runnable到UIThread或普通Thread,都支持延迟发送,这个工具很实用.
- 生产环境都有token,封装自动请求token更新token,app长期不用token过期跳转登录页面(拦截器功能).
- 添加最小宽度适配方案, 目前全球主流适配方案.几乎适配所有手机.适配方案技术细节https://www.jianshu.com/p/1302ad5a4b04
1、准备工作
网上有很多MVVM入门资料,在此就不再阐述什么是MVVM了,不清楚的朋友可以先去了解一下。
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.java、MultiRecycleViewModel.java、fragment_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
node-connect
337.3kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
frontend-design
83.2kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
openai-whisper-api
337.3kTranscribe audio via OpenAI Audio Transcriptions API (Whisper).
commit-push-pr
83.2kCommit, push, and open a PR
