其他分享
首页 > 其他分享> > Kotlin的魔能机甲——KtArmor(三)

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

作者:互联网

前言

继上篇说到, KtArmor-MVP的插件使用。我们可以快速创建基本的模板代码,但是在编写业务代码时候,不熟悉KtArmor-MVP框架, 不知其然,无法驾驭这个魔能机甲 。所以这篇我先从BaseActivity 开始说起,介绍KtArmor—MVP 的用法,“深入源码”解析,带你走进 KtArmor-MVP。

Activity

KtArmor-MVP 框架主要包含3个主要的Activity

它们之间继承关系如下:

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,复写对应方法进行扩展。下面是方法具体描述:

可以适用于 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基本用法。

在 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.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()
    }
}

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类, 在这里可以配置自己的参数进行扩展, 相关参数如下:

SharedPreferences

KtArmor-MVP 通过代理方式,封装了 SharedPreferences基本操作.

例如

var account by Preference(Key.ACCOUNT, "")

定义了一个 account 变量,传递对应Sp 存储的key,和默认值 “” (空串, 说明account 是 String 类型)
然后直接当正常变量使用, 如下直接赋值
就可以修改 Sp 中keyKey.ACCOUNT 的值了。代码如下

account = "123"

tryCatch

        // 传统的 tryCatch
        try{
            // TODO
        }catch (e: Exception){
            // TODO 
        }
        
        //  KtArmor-MVP 扩展
        tryCatch({
            // TODO
        })

        //  KtArmor-MVP 扩展
        tryCatch({
            // TODO
        }, {
            // TODO
        })

扩展函数

最后

以上是KtArmor-MVP 的全部内容,后续框架有更新,也会更新相关文档。

还是那句话,KtArmor-MVP 封装了基本 MVP结构的框架,是一款小而美的框架,麻雀虽小五章俱全。封装了基础的功能,小的项目,或者测试项目可以直接拿来用,省时省力。希望大家喜欢~

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

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

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

KtArmor-MVP 源码传送门

感谢阅读,下次再见

标签:MVP,初始化,KtArmor,Kotlin,override,Activity,fun,机甲
来源: https://blog.csdn.net/weixin_40595516/article/details/99589486