前言

继上篇说到, 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 = trueopen fun initWidows() {}abstract fun getLayoutId(): Intopen 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 布局
  • initBeforeinitView() 之前, setContentView()方法 之后的初始化方法。
  • initView:初始化控件view 方法.
  • initListener:初始化 控件view 相关 listener 方法。
  • initData:初始化数据方法

可以适用于 APP 启动页面简单展示页面等, 不涉及到Presenter 的 Activity

ToolbarActivity

abstract class ToolbarActivity : BaseActivity() {var toolbarTitle: String = ""set(value) {field = valuesupportActionBar?.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: Poverride fun initBefore() {presenter = bindPresenter()}abstract fun bindPresenter(): Poverride 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

BaseFragmentMvpFragment 的实现和 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: Stringget() = API.BASE_URLoverride val readTimeOut: Longget() = //TODOoverride val writeTimeOut: Longget() = //TODOoverride val connectTimeOut: Longget() = //TODOoverride 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 中keyKey.ACCOUNT 的值了。代码如下

account = "123"
复制代码

tryCatch

        // 传统的 tryCatchtry{// 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 IntR.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结构的框架,是一款小而美的框架,麻雀虽小五章俱全。封装了基础的功能,小的项目,或者测试项目可以直接拿来用,省时省力。希望大家喜欢~

最后,若有不妥,望小伙伴们指出。

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

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

KtArmor-MVP 源码传送门

感谢阅读,下次再见

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

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

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

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

  2. Kotlin的魔能机甲——KtArmor(一)

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

  3. 阿俊带你用Kotlin刷算法(三)

    本系列通过Java和Kotlin这两种语言来解决力扣上面的算法题,由于本人算法菜鸟一枚,可能部分题目并不是最优题解,希望能和各位大神共同讨论~ 阿俊带你用Kotlin刷算法(一) 阿俊带你用Kotli ...

  4. Kotlin修炼指南(三)——奇技淫巧

    Kotlin作为Android开发的首选语言,为开发者提供了大量的语法糖和技巧,让开发者可以专注于需求开发,而将语言所带来的影响减少到最少.Java和Kotlin最大的区别,实际上在于Kotlin的函 ...

  5. Kotlin学习笔记 第三章 函数 高阶函数 lambda表达式 内联函数

    参考链接 Kotlin官方文档 https://kotlinlang.org/docs/home.html 中文网站 https://www.kotlincn.net/docs/reference/p ...

  6. Kotlin学习日志(三)控制语句

    一.条件分支 1.1 简单分支 最简单的分支莫过于if-else了吧,Java中相信都用过,那么在Kotlin中又是怎么用的呢?其实也比较类似,来看看吧! 布局文件中: <TextViewand ...

  7. Kotlin骚气写法 三

    文章目录 ViewGroup获取ChildView集合 inline noinline crossinline比较 Kotlin 简化 Parcelable orEmpty() kotlin 代理 关 ...

  8. Kotlin学习笔记(三):Kotlin中的函数

    一.函数的特性语法 函数的几种声明形式 //普通声明形式fun sayHello(str: String){print(str)}//允许参数有默认值,可用于方法重载fun printName(str ...

  9. 为数不多的人知道的 Kotlin 技巧及解析(三)

    本文没有什么奇淫技巧,都是一些在实际开发中常用的技巧 Google 引入 Kotlin 的目的就是为了让 Android 开发更加方便,自从官宣 Kotlin 成为了 Android 开发的首选语言之 ...

最新文章

  1. 机器学习与深度学习常见面试问题与答案
  2. 利用cheat engine以及VC编写游戏修改器
  3. 指针数组,数组指针,函数指针,main函数实质,二重指针,函数指针作为参数,泛型函数
  4. Django中object.all
  5. C++ opengl 使视野转头移动(站桩看世界)
  6. python分解word文档为多个_用python批量处理word文档
  7. 虎牙、斗鱼正式达成合并协议;​中国广电正式成立,或催生5G发展新格局;Linux 5.9 释出|极客头条
  8. Oracle数据库中scott用户不存在的解决方法
  9. 怎么在堆叠柱状图中体现百分比_微生物门类堆叠柱状图一文解决
  10. Ubuntu安装文泉驿-微米黑字体
  11. easyui学习笔记5—panel加载其他的页面
  12. EXCEL常用技巧总结
  13. 弹跳机器人 桌游_《碰撞机器人 Ricochet Robots 》介绍
  14. MySQL limit后面加变量
  15. 【学习笔记之Openlayers3】要素保存篇(第四篇)
  16. chap0x10 实战fail2ban防止Basic认证暴力破解和SSH口令爆破
  17. Outlook创建不了Skype会议的解决方案
  18. 【JZOJ 100029】【NOIP2017提高A组模拟7.8】陪审团 (贪心+排序)
  19. 联想hx系列服务器,联想超融合HX系列产品介绍.pptx
  20. 清华开源virtual—box5.1下载

热门文章

  1. pppoe linux 配置文件,arm-linux配置pppoe
  2. h5支付 jsapi支付 扫码支付(场景二)
  3. 全网最全AD16——PCB布局
  4. 微信小程序+nginx+php+mysql实现数据库管理【第三期】php代码公布
  5. wamp3.0.6配置https + Nginx转发 + 满足微信小程序的接口调用域名
  6. 深圳外籍国际学校ib成绩如何?
  7. Springboot JAR包获取外置配置文件(打包分离出配置文件)
  8. Photoshop 如何玩转渐变映射?
  9. 三只小猪的思路解析及其C语言代码
  10. HTML使svg整体自适应网页变化、以元素颜色填充、隐藏显示