①Model:用于存储数据。它负责处理领域逻辑以及与数据库或网络层的通信。
②View:UI层,提供数据可视化界面,并跟踪用户的操作,以便通知presenter。
③Presenter:从Model层获取数据,并且应用UI逻辑来决定显示什么。它管理View的状态,并且根据来自于View的用户的输入执行动作。
实现mvp模式的核心点就是将view层和presenter绑定,将view层和model层解耦
首先,我们先三个基本的接口:
/**
*View层接口
*/
interface IView {
fun getContext(): Context?
fun getRootViews(): View?
fun getView(id: Int): T
fun getActivity(): Activity?
fun getFragment(): Fragment?
}
/**
* module层接口
* */
interface IModule {
}
/**
* Presenter层接口
* */
interface IPresenter {
fun onCreate(savedInstanceState: Bundle?, mContext: Context?)
fun onResume()
fun onStart()
fun onRestart()
fun onPause()
fun onStop()
fun onDestroy()
fun onSaveInstanceState(outState: Bundle)
fun onRestoreInstanceState(savedInstanceState :Bundle)
fun onActivityResult( requestCode :Int, resultCode :Int, data : Intent)
}
View层主要是获取Activity,布局文件等操作
Presenter层主要是控制Activity生命周期等
Module层就是用户根据自己的业务逻辑具体的自己去定义
接下来我们就利用反射+注解,在系统启动activity的时候,自动的生成相应的presenter实例,这样就不用手动去绑定view和presenter了
创建一个注解:
@Retention(AnnotationRetention.RUNTIME)
annotation class Request(val value:KClass<*>)
在运行时生效,传入kotlin的Class实例KClass
采用工厂模式来生产presenter
先创建一个工厂模式的接口:
interface IPresenterFactory {
/**
* 创建presenter
* */
fun createPresenter():P
}
因为我的Presenter需要等到运行的时候才会知道是哪个,所以使用泛型P代表
创建具体的Presenter工厂类,在静态方法findClass中,通过传入的Activity获得Activity的注解,并通过注解获得相应的presenter的Class
在createPresenter方法中,通过presenter的Class反射生成presenter对象
class PresenterFactory() :IPresenterFactory
{
private var presenterKClass :KClass<*> ?=null
constructor(presenterKClass :KClass<*>): this(){
this.presenterKClass =presenterKClass
}
companion object{
fun
findClass(viewClass:Class<*>) : PresenterFactory
{
val annotation = viewClass.getAnnotation(Request::class.java)
val value:KClass<*> =annotation.value
return PresenterFactory(value)
}
}
override fun createPresenter(): P {
return presenterKClass?.java!!.newInstance() as P
}
}
创建一个BasePresenter,实现IPresenter接口,将具体的View层的实例传过来。因为不知道具体的View是哪一个,所以使用泛型T表示
abstract class BasePresenter :IPresenter{
protected var mView: @UnsafeVariance T? = null
fun attachViewCompont(view: T) {
mView = view
}
fun detechViewCompont() {
mView = null
}
abstract fun setListeners()
}
为了实现设计模式的单一性原则,我们增加一个工厂类的代理类,来控制presenter的创建,已及view的绑定等操作:
class PresenterDelegate() where P:BasePresenter,V:IView {
private var presenterFactory :IPresenterFactory?=null
private var presenter :P ?=null
constructor(presenterFactory :IPresenterFactory
):this(){
this.presenterFactory =presenterFactory
}
open fun getPresenter():P{
if(presenter!=null){
return presenter!!
}
if (presenterFactory != null) {
if (presenter == null) {
presenter = presenterFactory?.createPresenter()
}
}
return presenter!!
}
open fun setPresenter(presenter: P) {
this.presenter = presenter
}
open fun bindViewCompont(view: IView) {
if (presenter == null) {
getPresenter()
}
if (presenter != null) {
presenter!!.attachViewCompont(view as V)
}
}
open fun unbindViewCompont() {
if (presenter != null) {
presenter!!.detechViewCompont()
}
}
}
创建一个BaseActivity,继承AppCompatActivity实现IView接口,在BaseActivity中,通过创建工厂类的装饰类,创建具体的P层,并将P层和View层绑定
abstract class BaseActivity :AppCompatActivity(),IView where P:BasePresenter,V:IView{
private var presenterDelegate = PresenterDelegate(PresenterFactory.findClass(javaClass))
protected val mViews = SparseArray()
protected var rootView: View? = null
protected var mDecorView: View? = null
open fun bindView(id: Int): T? {
var view: T? = mViews[id] as T
if (view == null) {
view = rootView?.findViewById(id)
mViews.put(id, view)
}
return view
}
override fun getContext(): Context? {
return this
}
override fun getRootViews(): View? {
return rootView
}
override fun getView(id: Int): T {
return bindView(id) as T
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
presenterDelegate.bindViewCompont(this)
rootView = layoutInflater.inflate(getLayoutId(), null, false)
setContentView(rootView)
initFields()
bindEventListener()
getPresenter().onCreate(savedInstanceState,this)
getPresenter().setListeners()
mDecorView = window.decorView
}
override fun onStart() {
super.onStart()
getPresenter().onStart()
}
override fun onRestart() {
super.onRestart()
getPresenter().onRestart()
}
override fun onResume() {
super.onResume()
getPresenter().onResume()
}
override fun onPause() {
super.onPause()
getPresenter().onPause()
}
override fun onStop() {
super.onStop()
getPresenter().onStop()
}
override fun onDestroy() {
getPresenter().onDestroy()
presenterDelegate.unbindViewCompont()
super.onDestroy()
}
protected open fun onSaveInstanceState(outState: Bundle?) {
super.onSaveInstanceState(outState!!)
getPresenter().onSaveInstanceState(outState!!)
}
protected open fun onRestoreInstanceState(savedInstanceState: Bundle?) {
super.onRestoreInstanceState(savedInstanceState!!)
getPresenter().onRestoreInstanceState(savedInstanceState!!)
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
getPresenter().onActivityResult(requestCode, resultCode, data!!)
}
/**
* 返回layout 布局文件的id
*
* @return
*/
abstract fun getLayoutId(): Int
/**
* 初始化其他属性
*/
abstract fun initFields()
/**
* 设置监听
*/
abstract fun bindEventListener()
open fun getPresenter(): P {
return presenterDelegate.getPresenter()
}
open fun setPresenter(presenter: P) {
presenterDelegate.setPresenter(presenter)
}
}
这样一个mvp架构就搭建完毕了,下面看看使用:
interface ITestView :IView {
fun setContent(string: String)
}
Module层:
class TestModule :IModule{
fun doNetWork(){
println("网络请求")
}
}
Presenter层:
class TestPresenter: BasePresenter() {
var module:TestModule? =null
override fun setListeners() {
}
override fun onCreate(savedInstanceState: Bundle?, mContext: Context?) {
module =TestModule()
}
override fun onResume() {
module?.doNetWork()
mView?.setContent("222222222")
}
override fun onStart() {
}
override fun onRestart() {
}
override fun onPause() {
}
override fun onStop() {
}
override fun onDestroy() {
}
override fun onSaveInstanceState(outState: Bundle) {
}
override fun onRestoreInstanceState(savedInstanceState: Bundle) {
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent) {
}
}
View层:
@Request(TestPresenter::class)
class TestActivity :BaseActivity(),ITestView {
var textView:TextView?=null
override fun getLayoutId(): Int {
return R.layout.activity_main
}
override fun initFields() {
textView =findViewById(R.id.txt)
}
override fun bindEventListener() {
}
override fun setContent(string: String) {
textView?.text =string
}
override fun getActivity(): Activity? {
return this
}
override fun getFragment(): Fragment? {
return null
}
}