前言

学习了Kotlin有一段时间了, 每次写项目/Demo的时候, 总是用到网络请求MVPMVVM常用工具类通用自定义View, 索性把这些整合到一起, 搭成一个Android的脚手架——KtArmor.

什么是KtArmor ?

KtArmor 寓意着 为Android 赋予战斗装甲, 方便开发者快速进行Android 开发。节约开发者开发时间。为了满足开发者需求, 我整合了两个分支, 分别对应着 MVP, MVVM.

  • MVP分支

    • 架构模式: MVP + Kotlin
    • 网络请求: Retrofit + Okhttp + Coroutine + RxJava
    • 功能
      • 基本BaseActivityBaseFragmentToolbarActivity封装
      • MVP框架封装 MvpActivityMvpFragmentBasePresenterBaseModel封装
      • 网络请求封装 BaseOkHttpClientBaseRetrofitRetrofitFactory
      • 常用控件PlaceHolderView(占位布局)LoadingView(加载框)
      • 常用扩展封装(SharedPreferencesStartActivityLogToast(不重复显示))等
      • MVP代码模板(ActivityPresenterContractModel)生成插件
      • ....
  • MVVM分支
    架构模式: MVVM+ Androidx + Kotlin + LiveData + ViewModel
    网络请求: Coroutines + Retrofit + Okhttp

MVP框架引入

先在 build.gradle(Project:XXXX) 的 repositories 添加:

allprojects {repositories {...maven { url "https://jitpack.io" }}
}
复制代码

然后在 build.gradle(Module:app) 的 dependencies 添加:

implementation 'com.github.hyzhan43:KtArmor:mvp-1.0.4'  // 根据github 引入最新版本即可
复制代码

快速上手

在Application 中初始化KtArmor 框架。新建一个application 类, 如 BaseApplication, 在 BaseApplication 中, 调用KtArmor的 init 方法, 进行初始化, 参数如下:

  • 第一个参数是application,
  • 第二个参数是对应RetrofitConfig 配置。
class BaseApplication: Application(){override fun onCreate() {super.onCreate()// 初始化KtArmorKtArmor.init(this, MyRetrofitConfig())}
}
复制代码

再新建一个 RetrofitConfig 配置类, 继承 BaseRetrofitConfig. 并复写 baseUrl 属性, 添加自己的 baseUrl。

class MyRetrofitConfig : BaseRetrofitConfig() {override val baseUrl: Stringget() = API.BASE_URL
}
复制代码

这样你就创建好了一个拥有Kotlin + Retrofit + Okhttp + Coroutine项目了。然后就可以愉快编写自己的业务代码了(●'◡'●)

Login 示例

1、LoginContract

我们先从简单登录流程来熟悉一下KtArmor。首先编写 LoginContract, 代码如下:

interface LoginContract {interface View : BaseContract.View {fun accountEmpty(msg: Int)fun passwordEmpty(msg: Int)fun loginSuc(loginRsp: LoginRsp)}interface Presenter : BaseContract.Presenter {fun login(account: String, password: String)}
}
复制代码

2、LoginActivity

然后新建一个LoginActivity, 继承 MvpActivity 并传递对应 LoginContract.Presenter 泛型,实现 LoginContract.View 接口, 代码如下:

class LoginActivity : MvpActivity<LoginContract.Presenter>(), LoginContract.View {override fun getLayoutId(): Int = R.layout.activity_loginoverride fun bindPresenter(): LoginContract.Presenter = LoginPresenter(this)override fun initListener() {super.initListener()mBtnLogin.setOnClickListener {mTilAccount.isErrorEnabled = falsemTilPassword.isErrorEnabled = false// 发起登录请求presenter.login(mEtAccount.str(), mEtPassword.str())}}override fun accountEmpty(msg: Int) {mTilAccount.isErrorEnabled = truemTilAccount.requestFocus()mTilAccount.error = getString(msg)}override fun passwordEmpty(msg: Int) {mTilPassword.isErrorEnabled = truemTilPassword.requestFocus()mTilPassword.error = getString(msg)}override fun loginSuc(loginRsp: LoginRsp) {toast("登陆成功!")}
}
复制代码
  • bindPresenter 方法返回 LoginPresenter 实例。
  • getLayoutId方法 返回LoginActivity 布局id。

这里 activity_login 里面是简单的 TextInputEditText,调用presenter, 发起登录请求。传递账号和密码。其中 str() 为 TextView 扩展方法。

  • str() 为扩展方法
// 获取text内容
fun TextView.str(): String {return this.text.toString()
}
复制代码

3、LoginPresenter

然后我们再看看对应 LoginPresenter 实现, 继承 BasePresenter,并传递对应 LoginContract.View

class LoginPresenter(view: LoginContract.View) : BasePresenter<LoginContract.View>(view), LoginContract.Presenter {override fun login(account: String, password: String) {if (account.isEmpty()) {view?.accountEmpty(R.string.account_empty)return}if (password.isEmpty()) {view?.passwordEmpty(R.string.password_empty)return}launchUI({view?.showLoading()val response = LoginModel.login(account, password)// 正常返回结果处理if (response.isSuccess()) {response.data?.let { view?.loginSuc(it) }} else {view?.showError(response.errorMsg)}}, {// TODO 异常处理})}
}
复制代码

在这里, 我们采用协程来实现切换线程操作。在 launchUI() 方法里面启动了一个 UI 协程,在这里调用 LoginModel 真正发起网络请求操作。

4、LoginModel

object LoginModel : BaseModel() {suspend fun login(account: String, password: String): BaseResponse<LoginRsp> {return launchIO { ApiManager.apiService.loginAsync(account, password).await() }}
}
复制代码

同样,LoginModel 需要继承 BaseModel(),并调用 launchIO 进行线程切换。切换到 IO线程 通过ApiManager.apiService 发起网络请求。然后调用 await() 返回结果。这里 ApiService 通过 RetrofitFactory创建, 传入 Service class。

object ApiManager {val apiService by lazy {RetrofitFactory.instance.create(ApiService::class.java)}
}
复制代码
interface ApiService {@POST(API.LOGIN)fun loginAsync(@Query("username") username: String,@Query("password") password: String): Deferred<BaseResponse<LoginRsp>>
}
复制代码

以上就是登录的全过程。看到这里,编写一个简单Login功能需要新建四个类,有点麻烦。有没有更便捷的方法的。那肯定!KtArmor 框架还有与之对应 KtArmor-MVP 插件,帮助开发者快速生成对应模板代码(ActivityPresenterContractModel)。

未完待续

这是KtArmor开篇的第一篇。大概讲解了KtArmor基本用法。后续会详细讲解框架的使用、以及插件的使用。至于KtArmor-MVVM 版目前还在测试阶段。后续也会陆续更新。敬请期待吧!
着急的小伙伴可以直接查看下文源码~

最后

KtArmor 框架是一款小而美的框架,也是我个人经验的积累, 总结。如有不妥, 望各位大佬指出。欢迎大家 pr交易, 一起交流学习。

KtArmor-MVP 源码传送门

Kotlin的魔能机甲——KtArmor插件篇(二)

Kotlin的魔能机甲——KtArmor(三)

下次再见

转载于:https://juejin.im/post/5d319e3651882540be3a2be7

Kotlin的魔能机甲——KtArmor(一)相关推荐

  1. Kotlin的魔能机甲——KtArmor(三)

    前言 继上篇说到, KtArmor-MVP的插件使用.我们可以快速创建基本的模板代码,但是在编写业务代码时候,不熟悉KtArmor-MVP框架, 不知其然,无法驾驭这个魔能机甲 .所以这篇我先从Bas ...

  2. Kotlin的魔能机甲——KtArmor网络调用封装(四)

    前言 继上次分享KtArmor的基础使用方法, 在网络请求逻辑上,在调用上,总感觉不够优雅直观,嵌套过深的问题,这样使得代码看起来臃肿,不美观.所以在这篇中,分享一下我在网络请求调用方面的 封装之路. ...

  3. Kotlin的圣光机甲——KtArmor通用流程篇 (二)

    前言 在前一篇中,介绍了 KtArmor-MVVM 简单的使用方法,但是这往往不是全部. 在持续迭代.维护下,发现功能越写越多,也相应复杂起来. 所以后续,我尽可能编写详细 说明文档,并且在源码编写 ...

  4. Android 快速开发框架, KtArmor 寓意着 为 Android 赋予战斗装甲, 方便开发者快速进行 Android 开发。

    KtArmor-MVVM 项目地址:hyzhan43/KtArmor-MVVM  简介: :ghost: Android 快速开发框架, KtArmor 寓意着 为 Android 赋予战斗装甲, 方 ...

  5. 新鲜出炉的 MVVM 脚手架——KtArmor-MVVM

    前言 时隔半年,我又又又回来了! 继 KtArmor-MVP 版推出后,收获到 "不少人" 反响,期望有个 MVVM 版. 我便立马投入 KtArmor-MVVM的开发中,由于工作 ...

  6. springboot实现SSE服务端主动向客户端推送数据,java服务端向客户端推送数据,kotlin模拟客户端向服务端推送数据

    SSE服务端推送 服务器向浏览器推送信息,除了 WebSocket,还有一种方法:Server-Sent Events(以下简称 SSE).本文介绍它的用法. 在很多业务场景中,会涉及到服务端向客户端 ...

  7. 在kotlin companion object中读取Bean,注入Bean对象

    在kotlin companion object中读取Bean,注入Bean对象 在使用kotlin时,或多或少地会使用到一些公共组件,如 http. mongo. redis相关的组件.   使用组 ...

  8. 在kotlin companion object中读取spring boot配置文件,静态类使用@Value注解配置

    在kotlin companion object中读取配置文件 静态类使用@Value注解配置 class Config {@Value("\${name}")fun setNam ...

  9. kotlin中继承父属性使用构造方法

    kotlin中继承父属性使用构造方法 1. 定义父类,给它两个属性: abstract class AbstractResponseMessage {private var success = tru ...

最新文章

  1. Android消息机制学习笔记
  2. mysql册_Mysql手册
  3. EPSON机器人SPLE+语言_简单实例
  4. mysql 140824,Oracle 12c创建可插拔数据库(PDB)及用户
  5. 使用vbs脚本检查网站是否使用asp.net
  6. es6 数组合并_JavaScript学习笔记(十九)-- ES6
  7. Java Web文件下载
  8. 【工具推荐】Adobe Reader 设置高亮颜色及深浅
  9. java中除数时刻0的异常_java中除数为0时出现的异常情况
  10. PHP处理微信昵称特殊符号过滤方法
  11. 林彪-怎样当好一名师长
  12. 电脑取消撤销快捷键是什么_都知道“撤消”快捷键是Ctrl Z,那“反撤消”是什么呢?...
  13. Sending build context to Docker daemon 解决办法
  14. 关于消防设施的RFID资产管理,RFID消防设施资产管理-新导智能
  15. win10蓝牙故障无法正常使用的有效解决方法
  16. requests使用代理IP
  17. golang 从windows 剪切板 (剪贴板)中读取bmp图片数据的方法
  18. Linux命令详解:md5sum
  19. R语言-文本文件读写 txt / csv / xlsx
  20. nginx一会儿正常,一会儿404,nginx一会儿访问网页1,一会儿访问网页2

热门文章

  1. 更亲民的轻薄旗舰 — 雷蛇灵刃 15 标准版长测
  2. ISTQB AL-TM连载系列05:测试出口准则评估与应对
  3. ChemDraw与Word(Office)不兼容问题的解决方法
  4. 从0开始的计算几何(一)———点与线
  5. 前端开发基础:html中的div什么意思?
  6. 聚观早报 | 保时捷将于月底挂牌上市;宁德时代首创MTB技术落地
  7. 实现全场景智慧,没产业生态不行
  8. MySQL详解 --- 内置函数
  9. java创建线程的四种方法
  10. 金融学 经济学字母和基本公式