• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    迪恩网络公众号

kmvvm: Kotlin+Flow+Retrofit+OKHttp+ViewBanding+ViewModel+LiveData封装的一个Kotli ...

原作者: [db:作者] 来自: 网络 收藏 邀请

开源软件名称:

kmvvm

开源软件地址:

https://gitee.com/catchpig/kmvvm

开源软件介绍:

Gitee 地址:kmvvm


Github 地址:kmvvm


CHANGE LOG

技术要点

  • 支持Flow+Retrofit+OkHttp实现链式http请求

  • 支持Rxjava+Retrofit+OkHttp实现链式http请求

  • 封装基类:BaseActivity、BaseVMActivity、BaseFragment、BaseVMFragment、RecycleAdapter、BaseViewModel

  • 封装工具扩展类:CalendarExt、ContextExt、DateExt、EditTextExt、GsonExt、RxJavaExt、StringExt、SnackbarExt

  • 引入LifeCycle,将ViewModel和Activity的生命周期绑定在一起

  • 将在Application中初始化移至到ContentProvider中,从而不用封装BaseApplication

  • APT(编译时注解)封装注解:Title、OnClickFirstDrawable、OnClickFirstText、OnClickSecondDrawable、OnClickSecondText、Prefs、PrefsField、StatusBar、FlowError、Adapter、GlobalConfig、ServiceApi

最低兼容:21

Gradle

1. 在Project的build.gradle中添加

allprojects {    repositories {        maven { url 'https://jitpack.io' }    }}

2. 在app的build.gradle的添加

apply plugin: 'kotlin-kapt' // 使用 kapt 注解处理工具apply plugin: 'kotlinx-serialization' //序列化

3. 在app的build.gradle的android下添加

buildFeatures {    viewBinding = true}

4. 添加依赖

Gitee

implementation "com.gitee.catchpig.kmvvm:mvvm:last_version"kapt "com.gitee.catchpig.kmvvm:compiler:last_version"

Github

implementation "com.github.catchpig.kmvvm:mvvm:last_version"kapt "com.github.catchpig.kmvvm:compiler:last_version"

使用

1. 配置全部参数

interface IGlobalConfig {    /**     * 标题栏高度     * @return Int     */    @DimenRes    fun getTitleHeight(): Int    /**     * 标题栏的返回按钮资源     * @return Int     */    @DrawableRes    fun getTitleBackIcon(): Int    /**     * 标题栏背景颜色     * @return Int     */    @ColorRes    fun getTitleBackground(): Int    /**     * 标题栏文本颜色     * @return Int     */    @ColorRes    fun getTitleTextColor(): Int    /**     * 标题栏下方是否需要横线     * @return Boolean     */    fun isShowTitleLine(): Boolean    /**     * 标题栏下方横线颜色     * @return Int     */    @ColorRes    fun getTitleLineColor(): Int    /**     * loading的颜色     * @return Int     */    @ColorRes    fun getLoadingColor(): Int    /**     * loading的背景颜色     * @return Int     */    @ColorRes    fun getLoadingBackground(): Int    /**     * RecyclerView的空页面ViewBinding     * @param parent ViewGroup     * @return ViewBinding     */    fun getRecyclerEmptyBanding(parent: ViewGroup): ViewBinding    /**     * 刷新每页加载个数     * @return Int     */    fun getPageSize(): Int    /**     * 刷新起始页的index(有些后台设置的0,有些后台设置1)     */    fun getStartPageIndex(): Int}

使用示例:

@GlobalConfigclass MvvmGlobalConfig : IGlobalConfig {    override fun getTitleHeight(): Int {        return R.dimen.title_bar_height    }    override fun getTitleBackIcon(): Int {        return R.drawable.back_black    }    override fun getTitleBackground(): Int {        return R.color.colorPrimary    }    override fun getTitleTextColor(): Int {        return R.color.white    }    override fun isShowTitleLine(): Boolean {        return true    }    override fun getTitleLineColor(): Int {        return R.color.color_black    }    override fun getLoadingColor(): Int {        return R.color.color_black    }    override fun getLoadingBackground(): Int {        return R.color.white    }    override fun getRecyclerEmptyBanding(parent: ViewGroup): ViewBinding {        return LayoutEmptyBinding.inflate(LayoutInflater.from(parent.context), parent, false)    }    override fun getPageSize(): Int {        return 16    }    override fun getStartPageIndex(): Int {        return 1    }}

2. Activity

  • 使用MVVM的继承BaseVMActivity
  • 不使用MVVM的继承BaseActivity'

2.1 标题注解使用

使用示例

Title其他注解参数,请看下方注解详情

//设置标题的文字@Title(R.string.child_title)class ChildActivity : BaseVMActivity<ActivityChildBinding, ChildViewModel>() 

如果标题栏文字要根据接口显示不同的文字,也有接口设置

class ChildActivity : BaseVMActivity<ActivityChildBinding, ChildViewModel>() {    @OnClickFirstDrawable(R.drawable.more)    fun clickFirstDrawable(v: View) {        updateTitle("更改标题")    }}

2.2 状态栏注解使用

使用示例

StatusBar其他注解参数,请看下方注解详情

//弃用注解@StatusBar(hide = true)class FullScreenActivity : BaseActivity<ActivityFullScreenBinding>()

2.3 标题右侧文字或图标按钮注解使用

使用示例

注解修饰的方法只能可以带View参数,也可以不带View参数,看自身的需求

@Title(R.string.child_title)class ChildActivity : BaseVMActivity<ActivityChildBinding, ChildViewModel>() {    @OnClickFirstDrawable(R.drawable.more)    fun clickFirstDrawable(v: View) {        SnackbarManager.show(bodyBinding.root, "第一个图标按钮点击生效")        updateTitle("nihao")    }    @OnClickFirstText(R.string.more)    fun clickFirstText() {        SnackbarManager.show(bodyBinding.root, "第一个文字按钮点击生效")        updateTitle("12354")    }    @OnClickSecondDrawable(R.drawable.more)    fun clickSecondDrawable(v: View) {        SnackbarManager.show(bodyBinding.root, "第二个图标按钮点击生效")        updateTitle("nihao")    }    @OnClickSecondText(R.string.more)    fun clickSecondText() {        SnackbarManager.show(bodyBinding.root, "第二个文字按钮点击生效")        updateTitle("12354")    }}

2.4 提示框

  • Android 11 之后,Toast已经不支持自定义Toast,原生的Toast是很难看的
  • 本框架使用SnackBar做提示框

使用示例

@OnClickSecondDrawable(R.drawable.more)fun clickSecondDrawable(v: View) {    snackBar("第二个图标按钮点击生效")}

3. Fragment

  • 使用MVVM的继承BaseVMFragment
  • 不使用MVVM的继承BaseFragment

3.1 提示框

  • Android 11 之后,Toast已经不支持自定义Toast,原生的Toast是很难看的
  • 本框架使用SnackBar做提示框

使用示例

snackbar.setOnClickListener {    snackBar("提示框")}

4. RecycleView

Adapter可以继承RecycleAdapter来使用,并在类上添加注解Adapter,RecycleAdapter使用了ViewBanding,只需要实现以下一个方法

使用示例

@Adapterclass UserAdapter(iPageControl: IPageControl) :    RecyclerAdapter<User, ItemUserBinding>(iPageControl) {    override fun bindViewHolder(holder: CommonViewHolder<ItemUserBinding>, m: User, position: Int) {        holder.viewBanding {            name.text = m.name        }    }}

5.刷新分页控件(RefreshRecyclerView)

  • RefreshRecyclerView集成了RefreshLayoutWrapper+RecyclerView

不用关心分页的逻辑,分页的刷新逻辑实现都在RefreshLayoutWrapper

  • 只需要设置LayoutManager和RecyclerAdapter,提供了setLayoutManager和setAdapter方法
  • 在获取到数据的时候调用updateData方法
  • 获取数据失败的时候调用updateError方法
  • 如果使用了lifecycleFlowRefresh方法,updateData方法和updateError方法都不用关心
  • 提供自定义属性recycler_background(设置RecyclerView的背景色)
<declare-styleable name="RefreshRecyclerView">    <attr name="recycler_background" format="color" /></declare-styleable>

使用示例

<LinearLayout 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" android:orientation="vertical">    <TextView android:layout_width="match_parent" android:layout_height="50dp"        android:background="@color/colorPrimary" android:gravity="center" android:text="文章"        android:textColor="@color/color_white" />    <com.catchpig.mvvm.widget.refresh.RefreshRecyclerView android:id="@+id/refresh"        android:layout_width="match_parent" android:layout_height="match_parent"        app:recycler_background="#445467">    </com.catchpig.mvvm.widget.refresh.RefreshRecyclerView></LinearLayout>
bodyBinding.refresh.run {    setOnRefreshLoadMoreListener { nextPageIndex ->        lifecycleFlowRefresh(viewModel.queryArticles(nextPageIndex), this)    }}

6. 网络请求

6.1只需要是接口类上加上注解ServiceApi,并使用NetManager.getService()获取对应的接口类

使用示例

@ServiceApi(    baseUrl = "https://www.wanandroid.com/",    responseConverter = ResponseBodyConverter::class,    interceptors = [RequestInterceptor::class],    debugInterceptors = [OkHttpProfilerInterceptor::class])interface WanAndroidService {    @GET("banner/json")    suspend fun banner(): List<Banner>}
object WanAndroidRepository {    private val wanAndroidService = NetManager.getService(WanAndroidService::class.java)    fun getBanners(): Flow<MutableList<Banner>> {        //这里如果用flowOf的话,方法上面必须加上suspend关键字        return flow {            emit(wanAndroidService.queryBanner())        }    }}
class IndexViewModel : BaseViewModel() {    fun queryBanners(): Flow<MutableList<Banner>> {        return WanAndroidRepository.getBanners()    }}
//Activity或者FragmentlifecycleFlowLoadingView(viewModel.queryBanners()) {    val images = mutableListOf<String>()    this.forEach {        images.add(it.imagePath)    }    bodyBinding.banner.run {        setImages(images)        start()    }}

6.2 Response转换器

6.2.1
  • 一般Response发返回结果会是如下
{	code:"SUCCESS",	errorMsg:"成功",	data:...}
  • 在code返回SUCEESSD的时候, 我们在Retrofit的Api接口里面只想拿到data的数据做返回,我们想在Converter里面处理掉code返回错误码的逻辑,就可以继承BaseResponseBodyConverter,内部已经实现了将response转化为data的逻辑

代码示例

class ResponseBodyConverter :    BaseResponseBodyConverter() {    override fun getResultClass(): KClass<out BaseResponseData<JsonElement>> {        return Result::class    }    override fun handlerErrorCode(errorCode: String, msg: String): Exception {        return NullPointerException()    }}
  • 再将实现了BaseResponseBodyConverter的类加到ServiceApi注解的responseConverter属性上
6.2.2

6.3 Activity和Fragment封装了网络请求方法(带lifecycleScope)

  • lifecycleFlowRefresh(flow: Flow<MutableList>,refresh: RefreshRecyclerView)-刷新+RecycleView的网络请求封装
  • lifecycleFlow(flow: Flow, callback: T.() -> Unit)-不带loading的网络请求封装
  • lifecycleFlowLoadingView(flow: Flow, callback: T.() -> Unit)-带loadingView的网络请求封装
  • lifecycleFlowLoadingDialog(flow: Flow, callback: T.() -> Unit)-带loadingDialog的网络请求封装

7. 注解使用

7.1 Title-标题

属性类型必须默认说明
valueStringRes标题内容
backgroundColorColorRes全局标题背景色标题背景色
textColorColorRes全局标题文字颜色标题文字颜色
backIconDrawableRes全局标题返回按钮图标标题返回按钮图标

7.2 OnClickFirstDrawable-标题上第一个图标按钮的点击事件

属性类型必须默认说明
valueDrawableRes按钮图片资源

7.3 OnClickFirstText-标题上第一个文字按钮的点击事件

属性类型必须默认说明
valueStringRes按钮文字内容

7.4 OnClickSecondDrawable-标题上第二个图标按钮的点击事件

属性类型必须默认说明
valueDrawableRes按钮图片资源

7.5 OnClickSecondText-标题上第二个文字按钮的点击事件

属性类型必须默认说明
valueStringRes按钮文字内容

7.6 StatusBar-状态栏

属性类型必须默认说明
hidebooleanfalse隐藏状态栏
enabledbooleanfalse状态栏是否可用
transparentbooleanfalse状态栏透明

7.7 Prefs-SharedPreferences注解生成器

属性类型必须默认说明
valueString""别名
modePrefsModePrefsMode.MODE_PRIVATE模式,对应PreferencesMode

7.8 PrefsField-SharedPreferences字段注解

属性类型必须默认说明
valueString""字段别名,如果为空则取修饰字段的参数名称

7.9 FlowError-Activity和Fragment中的Flow的onError方法统一处理

7.10 Adapter-RecyclerAdapter的继承类注解,加上此注解之后可以自动找到对应的layout资源

7.11 GlobalConfig-全局参数配置

  • 注解在IGlobalConfig接口的实现类上面

7.12 ServiceApi-网络请求接口注解类

属性类型必须默认说明
baseUrlStringretrofit的baseurl
responseConverterConverter接收数据转换器
connectTimeoutLong5000http的超时时间
readTimeoutLong5000http读取超时时间
interceptorsInterceptorInterceptorhttp拦截器
debugInterceptorsInterceptorInterceptordebug模式下的http拦截器,只有NetManager.setDebug(true),才会生效

8. 文件下载器(DownloadManager))

DownloadManager.download(downloadUrl, {        //下载完成回调    }, { downloadProgress ->        //下载进度回调    })
  • DownloadCallback
interface DownloadCallback {        /**         * 开始下载         */        fun onStart()            /**         * 下载成功         * @param path 本地保存的地址         */        fun onSuccess(path:String)            /**         * 下载完成         */        fun onComplete()    		/**     	 * 下载进度         * @param downloadProgress DownloadProgress         */        fun onProgress(downloadProgress: DownloadProgress)            /**         * 下载错误         * @param t 错误信息         */        fun onError(t:Throwable)    }
DownloadManager.multiDownload(downloadUrls, {         //下载完成回调    }, { downloadProgress ->        //下载进度回调    })

鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
上一篇:
itriton-uniapp: @itriton/uniapp是基于uni-app生态开发的组件库发布时间:2022-03-24
下一篇:
TTWORDS: 天天背单词——日语版发布时间:2022-03-24
热门推荐
热门话题
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap