Kotlin的魔能机甲——KtArmor(三)
作者:互联网
前言
继上篇说到, KtArmor-MVP的插件使用。我们可以快速创建基本的模板代码,但是在编写业务代码时候,不熟悉KtArmor-MVP框架, 不知其然,无法驾驭这个魔能机甲
。所以这篇我先从BaseActivity 开始说起,介绍KtArmor—MVP 的用法,“深入源码”
解析,带你走进 KtArmor-MVP。
Activity
KtArmor-MVP 框架主要包含3个主要的Activity
- BaseActivity
- ToolbarActivity
- MvpActivity
它们之间继承关系如下:
MvpActivity > ToolbarActivity > BaseActivity
然后我们来看看他们具体的实现
BaseActivity
abstract class BaseActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// 在界面未初始化之前调用的初始化窗口
initWidows()
if (initArgs(intent.extras)) {
setContentView(getLayoutId())
initBefore()
initView()
initListener()
initData()
} else {
finish()
}
}
open fun initArgs(bundle: Bundle?): Boolean = true
open fun initWidows() {}
abstract fun getLayoutId(): Int
open fun initBefore() {}
open fun initView() {}
open fun initListener() {}
open fun initData() {}
}
BaseActivity
基本的模板结构,定义了基本的Activity 初始化的方法。可以继承BaseActivity,复写对应方法进行扩展。下面是方法具体描述:
initWidows
: 在界面(setContentView
)未初始化之前调用的初始化窗口方法initArgs
: 初始化界面参数方法(Activity 之间跳转传递参数), 该方法 默认返回True
, 显示Activity, 否则返回False, 不显示Activity。getLayoutId
:初始化 Activity 的 layout 布局initBefore
:initView()
之前,setContentView()
方法 之后的初始化方法。initView
:初始化控件view 方法.initListener
:初始化 控件view 相关 listener 方法。initData
:初始化数据方法
可以适用于
APP 启动页面
,简单展示页面
等, 不涉及到Presenter 的Activity
ToolbarActivity
abstract class ToolbarActivity : BaseActivity() {
var toolbarTitle: String = ""
set(value) {
field = value
supportActionBar?.title = value
}
override fun initView() {
super.initView()
initToolbar()
}
/**
* Toolbar id must be toolbar
*/
private fun initToolbar() {
findViewById<Toolbar>(R.id.toolbar)?.let { toolbar ->
setSupportActionBar(toolbar)
supportActionBar?.let {
it.setDisplayHomeAsUpEnabled(true)
it.setDisplayShowHomeEnabled(true)
}
}
}
override fun onOptionsItemSelected(item: MenuItem?): Boolean {
when (item?.itemId) {
//将滑动菜单显示出来
android.R.id.home -> {
finish()
return true
}
}
return super.onOptionsItemSelected(item)
}
}
ToolbarActivity
继承 BaseActivity, 方便于显示 Toolbar,在项目中挺常用的,所以就封装这个Toolbar基本用法。
- Toolbar title 的显示
- Toolbar 返回键(
android.R.id.home
)的关闭操作。 toolbarTitle
: 可以更改 toolbar 对应的 title
在 Activity 的 xml 引入 Toolbar控件, 并且 id 必须为
toolbar
,否则不会调用initToolbar
初始化方法 !!!
MvpActivity
abstract class MvpActivity<P : BaseContract.Presenter> : ToolbarActivity(), BaseContract.View {
lateinit var presenter: P
override fun initBefore() {
presenter = bindPresenter()
}
abstract fun bindPresenter(): P
override fun showError(@StringRes msgRes: Int) {
showError(getString(msgRes))
}
override fun showError(msg: String) {
toast(msg)
hideLoading()
}
override fun showLoading() {}
override fun hideLoading() {}
override fun onDestroy() {
super.onDestroy()
if (::presenter.isInitialized) {
presenter.detachView()
}
}
}
MvpActivity 同样是继承ToolbarActivity, 实现了基本 BaseContract.View
, 管理着 Presenter 生命周期
。子类需要实现 bindPresenter()
方法,传递对应的 Presenter。 然后就可以调用 Presenter 进行后续的操作。
- 封装了
Presenter
初始化,销毁 - 复写
showError()
,showLoading()
,hideLoading()
等方法。(简单toast 了)
::presenter.isInitialized
意思是判断 Presenter 是否懒加载初始化, 防止未初始化,抛异常。
后续可能会通过泛型T
, 反射生成Presenter,减少重复操作
Fragment
BaseFragment
、MvpFragment
的实现和 Activity 实现异曲同工,这里就不过多介绍了~
Presenter
abstract class BasePresenter<V : BaseContract.View>(view: V) : BaseContract.Presenter{
val view: V?
get() = mViewRef.get()
// View 接口类型的弱引用
private var mViewRef = WeakReference(view)
val presenterScope: CoroutineScope by lazy {
CoroutineScope(Dispatchers.Main + Job())
}
fun launchUI(block: suspend CoroutineScope.() -> Unit, error: ((Throwable) -> Unit)? = null) {
presenterScope.launch {
tryCatch({
block()
}, {
error?.invoke(it) ?: view?.showError(it.toString())
})
}
}
override fun detachView() {
mViewRef.clear()
// 取消掉 presenterScope创建的所有协程和其子协程。
presenterScope.cancel()
}
}
- 绑定
View
的初始化, 销毁, 采用 弱引用方式, 防止内存泄露。 launchUI
封装 协程,切换到 Main线程方法,并进行tryCatch 捕获异常。presenterScope
的销毁,绑定到 对应 UI界面 的onDestory
方法,防止内存泄露。
Model
abstract class BaseModel {
suspend fun <R> launchIO(block: suspend CoroutineScope.() -> R) = withContext(Dispatchers.IO) {
block()
}
}
BaseModel 相对简单, 封装了协程切换 IO 线程的操作.
后续可能添加相关 DB 相关操作
Retrofit
class MyRetrofitConfig : BaseRetrofitConfig() {
override val baseUrl: String
get() = API.BASE_URL
override val readTimeOut: Long
get() = //TODO
override val writeTimeOut: Long
get() = //TODO
override val connectTimeOut: Long
get() = //TODO
override fun initRetrofit(): Retrofit {
// 默认实现 BaseRetrofit.init()
return Retrofit.Builder()
.baseUrl(KtArmor.retrofit.baseUrl)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(CoroutineCallAdapterFactory())
.client(KtArmor.retrofit.initOkHttpClient())
.build()
}
override fun initOkHttpClient(): OkHttpClient {
// 可以传递 Interceptor 进行网络请求拦截
return BaseOkHttpClient.init(TokenInterceptor.create())
}
}
Retrofit 相关网络操作, 可以继承BaseRetrofitConfig
类, 在这里可以配置自己的参数进行扩展, 相关参数如下:
baseUrl
: 网络请求的 baseUrl
initRetrofit
: 为初始化 Retrofit方法,可以返回自定Retrofit
。- 默认实现
BaseRetrofit.init()
- 默认实现
initOkHttpClient
初始化 OkHttp的方法,可以返回自定Okhttp
。- 默认实现
BaseOkHttpClient.init()
init()
方法可以传入对应的Interceptor
, 进行拦截网络操作.readTimeOut
,writeTimeOut
,connectTimeOut
可以复写网络连接超时属性
- 默认实现
SharedPreferences
KtArmor-MVP 通过代理方式,封装了 SharedPreferences基本操作.
- 通过定义一个变量,并通过
by Preference
代理 - 传递 Sp的
key
和对应的defaultValue
值
例如
var account by Preference(Key.ACCOUNT, "")
定义了一个 account 变量,传递对应Sp 存储的key,和默认值 “” (空串, 说明account 是 String
类型)
然后直接当正常变量使用, 如下直接赋值
就可以修改 Sp 中key
为 Key.ACCOUNT
的值了。代码如下
account = "123"
tryCatch
// 传统的 tryCatch
try{
// TODO
}catch (e: Exception){
// TODO
}
// KtArmor-MVP 扩展
tryCatch({
// TODO
})
// KtArmor-MVP 扩展
tryCatch({
// TODO
}, {
// TODO
})
扩展函数
Toast
扩展, 不重复showToast,多次点击会替换支持
:Context,Activity, Fragment 扩展扩展参数
:string
(或 @StringRes ),duration
- 全局 Toast, 通过 Toasts.show(xx)
sp
,dp
相互转化支持
:Float to Float, Int to Int
Log
支持
:string.showLog()示例
:"我是Log".showLog()
R.color.xxx -> Color Int
,R.drawable.xxx -> Drawable
扩展支持
:Context,View 下扩展示例
:val defaultColor: Int = context.getColorRef(R.color.xxx) val defaultDrawable: Drawable? = context.getDrawableRef(R.drawable.xxx)
startActivity
参照 anko 的 startActivity (fuzhi)支持
:Context, Fragment 下扩展示例
:startActivity<XXXActivity>(key to value)
View
相关扩展TextView
扩展示例
:// 直接获取 TextView 的 text 值 mTvAccount.str()
- View 显示隐藏扩展
示例
:mIvImage.visible()
- 显示,关闭软键盘扩展
支持
:View, Activity示例
:activity.hideKeyboard()
- …
最后
以上是KtArmor-MVP 的全部内容,后续框架有更新,也会更新相关文档。
还是那句话,KtArmor-MVP 封装了基本 MVP结构的框架,是一款小而美的框架,麻雀虽小五章俱全。封装了基础的功能,小的项目,或者测试项目可以直接拿来用,省时省力。希望大家喜欢~
最后,若有不妥,望小伙伴们指出。
KtArmor-MVP 源码传送门
感谢阅读,下次再见
标签:MVP,初始化,KtArmor,Kotlin,override,Activity,fun,机甲 来源: https://blog.csdn.net/weixin_40595516/article/details/99589486