前言
学习了Kotlin有一段时间了, 每次写项目/Demo
的时候, 总是用到网络请求
、MVP
、MVVM
、常用工具类
、通用自定义View
, 索性把这些整合到一起, 搭成一个Android的脚手架——KtArmor
.
什么是KtArmor ?
KtArmor
寓意着 为Android 赋予战斗装甲
, 方便开发者快速进行Android 开发。节约开发者开发时间。为了满足开发者需求, 我整合了两个分支, 分别对应着 MVP
, MVVM
.
- MVP分支
- 架构模式:
MVP
+Kotlin
- 网络请求:
Retrofit
+Okhttp
+Coroutine
+RxJava
- 功能
- 基本
BaseActivity
、BaseFragment
、ToolbarActivity
封装 - MVP框架封装
MvpActivity
、MvpFragment
、BasePresenter
、BaseModel
封装 - 网络请求封装
BaseOkHttpClient
、BaseRetrofit
、RetrofitFactory
- 常用控件
PlaceHolderView(占位布局)
,LoadingView(加载框)
- 常用扩展封装(
SharedPreferences
、StartActivity
、Log
、Toast
(不重复显示))等 - MVP代码模板(
Activity
、Presenter
、Contract
、Model
)生成插件 - ....
- 基本
- 架构模式:
- 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()
// 初始化KtArmor
KtArmor.init(this, MyRetrofitConfig())
}
}
复制代码
再新建一个 RetrofitConfig 配置类, 继承 BaseRetrofitConfig
. 并复写 baseUrl
属性, 添加自己的 baseUrl。
class MyRetrofitConfig : BaseRetrofitConfig() {
override val baseUrl: String
get() = 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_login
override fun bindPresenter(): LoginContract.Presenter = LoginPresenter(this)
override fun initListener() {
super.initListener()
mBtnLogin.setOnClickListener {
mTilAccount.isErrorEnabled = false
mTilPassword.isErrorEnabled = false
// 发起登录请求
presenter.login(mEtAccount.str(), mEtPassword.str())
}
}
override fun accountEmpty(msg: Int) {
mTilAccount.isErrorEnabled = true
mTilAccount.requestFocus()
mTilAccount.error = getString(msg)
}
override fun passwordEmpty(msg: Int) {
mTilPassword.isErrorEnabled = true
mTilPassword.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
插件,帮助开发者快速生成对应模板代码(Activity
、Presenter
、Contract
、Model
)。
未完待续
这是KtArmor开篇的第一篇。大概讲解了KtArmor基本用法。后续会详细讲解框架的使用、以及插件的使用。至于KtArmor-MVVM
版目前还在测试阶段。后续也会陆续更新。敬请期待吧!
着急的小伙伴可以直接查看下文源码
~
最后
KtArmor
框架是一款小而美的框架,也是我个人经验的积累, 总结。如有不妥, 望各位大佬指出。欢迎大家 pr交易
, 一起交流学习。
KtArmor-MVP 源码传送门
Kotlin的魔能机甲——KtArmor插件篇(二)
Kotlin的魔能机甲——KtArmor(三)
下次再见