给大家推荐一下我最近刚写好的“可配置的ScrollView框架”,凡是采用scrollView结构的业务页面都可以采用这个框架。该框架主要有以下几个优点:
1、scrollView中的每个模块位置走配置,有一个configuration类统一管理
2、业务代码模块化。activity里不再充斥了各种业务代码,每个模块的业务代码分别在自己的模块里实现
3、layout布局模块化。每个模块的布局都写在单独的layout里,activity的layout只有一个scrollView作为container
4、模块间可通信。采用
中介者模式
,模块间很好地解耦,可以轻松地在模块A中通知模块B去修改
5、模块中可拿到activity的生命周期,彻底实现了业务代码模块化
6、框架结构严格按照
mvp
的思想设计,层次清晰
下面来介绍一下我的设计思想。
先看一下框架结构

首先看一下Activity代码:
class MainActivity : AppCompatActivity(), IView {
private val mModuleConfiguration = ModuleConfiguration()
private lateinit var mContainer: LinearLayout
private lateinit var mPresenter: Presenter
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
initViews()
init()
}
private fun initViews() {
mContainer = findViewById(R.id.container)
}
private fun init() {
mPresenter = Presenter(this, this)
mModuleConfiguration.init(this, mPresenter).doConfigure().assemblePage(mContainer)
mModuleConfiguration.onViewCreated()
mPresenter.startDrawUI()
}
override fun onDestroy() {
super.onDestroy()
mModuleConfiguration.onDestroy()
}
override fun onResume() {
super.onResume()
mModuleConfiguration.onResume()
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
mModuleConfiguration.onActivityResult(requestCode, resultCode, data)
}
override fun refreshModule(type: String, fromNetwork: Boolean) {
mModuleConfiguration.getModule(type)?.refresh(fromNetwork)
}
}
可以看到,activity中有一个
ModuleConfiguration
类负责管理配置各个module,它主要负责控制每个module位置,添加新的module,控制每个module的生命周期回调,模块间通信。
使用起来也非常方便:
mModuleConfiguration.init(this, mPresenter).doConfigure().assemblePage(mContainer)
采用一个链式调用就可以完成模块的配置。
接下来看一下每个module的结构
class BModule : BaseModule(), View.OnClickListener {
override fun onClick(v: View?) {
notifyAModule()
}
override fun refresh(fromNetwork: Boolean) {
}
override fun getModuleView(): View {
mView = LayoutInflater.from(mContext).inflate(R.layout.layout_b,
getParentView(), false)
return mView
}
override fun onViewCreated() {
super.onViewCreated()
mView.setOnClickListener(this)
}
private fun notifyAModule() {
mMediator.notifyAdoSomething()
}
override fun onDestroy() {
super.onDestroy()
}
override fun onResume() {
super.onResume()
}
override fun onResumeAndLoginStateChanged() {
super.onResumeAndLoginStateChanged()
}
}
这里不用多说了吧,层次非常清晰。每个module有一个基类BaseModule:
abstract class BaseModule {
lateinit var mContext: Context
lateinit var mView: View
lateinit var mParent: ViewGroup
lateinit var mPresenter: Presenter
lateinit var mMediator: Mediator
open fun init(context: Context, presenter: Presenter, mediator: Mediator) {
this.mContext = context
this.mPresenter = presenter
this.mMediator = mediator
}
open fun onViewCreated() {
}
open fun onDestroy() {
}
open fun onResume() {
}
open fun onResumeAndLoginStateChanged() {
}
open fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
}
fun bind(parent: ViewGroup) {
if (parent == null) {
return
}
mParent = parent
var view = getModuleView()
if (view == null || view.parent != null) {
return
}
view.visibility = View.VISIBLE
parent.addView(view)
}
abstract fun getModuleView(): View
fun getParentView(): ViewGroup {
return mParent
}
abstract fun refresh(fromNetwork: Boolean)
}
看到这里,你应该已经大致知道了我的设计思想了。下面就是mvp架构的具体实现:
首先是View层:
demo里view层只有一个方法,
interface IView {
fun refreshModule(type: String, fromNetwork: Boolean)
}
要想刷新哪个module,只需要把对应的type传进来。
interface IPresenter {
fun onDataRes(type: String, fromNetwork: Boolean)
fun getModel(): Model
}
接下来看Presenter层:
这里负责接收model层处理好的数据,并通知ui层更新ui。
最后看一下Model层:
interface IModel {
fun requestDataARes(modelA: ModelA, fromNetwork: Boolean)
fun requestDataBRes(modelB: ModelB, fromNetwork: Boolean)
fun requestDataCRes(modelC: ModelC, fromNetwork: Boolean)
fun requestDataDRes(modelD: ModelD, fromNetwork: Boolean)
}
这里负责处理各个网络请求的数据,model层主要负责:发送网络请求、将网络请求回来的数据进行内存和文件缓存。
到这里
mvp
就介绍完了,代码没有全部列出,后面会奉上demo地址。
最后有一个MemoryCache类,可以在里面轻松拿到所有的内存缓存。
object MemoryCache {
fun setModelA(presenter: IPresenter, modelA: ModelA) {
presenter.getModel().memoryCache.modelA = modelA
}
fun getModelA(presenter: IPresenter): ModelA? {
return presenter.getModel().memoryCache.modelA
}
fun setModelB(presenter: IPresenter, modelB: ModelB) {
presenter.getModel().memoryCache.modelB = modelB
}
fun getModelB(presenter: IPresenter): ModelB? {
return presenter.getModel().memoryCache.modelB
}
fun setModelC(presenter: IPresenter, modelC: ModelC) {
presenter.getModel().memoryCache.modelC = modelC
}
fun getModelC(presenter: IPresenter): ModelC? {
return presenter.getModel().memoryCache.modelC
}
}
这个框架基本上就可以支持任何业务页面的开发了,层次非常清晰。奉上demo地址。