• Android 使用kotlin+注解+反射+泛型实现MVP架构


    一,MVP模式的定义

    ①Model:用于存储数据。它负责处理领域逻辑以及与数据库或网络层的通信。

    ②View:UI层,提供数据可视化界面,并跟踪用户的操作,以便通知presenter。

    ③Presenter:从Model层获取数据,并且应用UI逻辑来决定显示什么。它管理View的状态,并且根据来自于View的用户的输入执行动作。

    实现mvp模式的核心点就是将view层和presenter绑定,将view层和model层解耦

    二,代码实现

    首先,我们先三个基本的接口:

    1. /**
    2. *View层接口
    3. */
    4. interface IView {
    5. fun getContext(): Context?
    6. fun getRootViews(): View?
    7. fun getView(id: Int): T
    8. fun getActivity(): Activity?
    9. fun getFragment(): Fragment?
    10. }
    1. /**
    2. * module层接口
    3. * */
    4. interface IModule {
    5. }
    1. /**
    2. * Presenter层接口
    3. * */
    4. interface IPresenter {
    5. fun onCreate(savedInstanceState: Bundle?, mContext: Context?)
    6. fun onResume()
    7. fun onStart()
    8. fun onRestart()
    9. fun onPause()
    10. fun onStop()
    11. fun onDestroy()
    12. fun onSaveInstanceState(outState: Bundle)
    13. fun onRestoreInstanceState(savedInstanceState :Bundle)
    14. fun onActivityResult( requestCode :Int, resultCode :Int, data : Intent)
    15. }

    View层主要是获取Activity,布局文件等操作

    Presenter层主要是控制Activity生命周期等

    Module层就是用户根据自己的业务逻辑具体的自己去定义

    接下来我们就利用反射+注解,在系统启动activity的时候,自动的生成相应的presenter实例,这样就不用手动去绑定view和presenter了

    创建一个注解:

    1. @Retention(AnnotationRetention.RUNTIME)
    2. annotation class Request(val value:KClass<*>)

    在运行时生效,传入kotlin的Class实例KClass

    采用工厂模式来生产presenter

    先创建一个工厂模式的接口:

    1. interface IPresenterFactory<P> {
    2. /**
    3. * 创建presenter
    4. * */
    5. fun createPresenter():P
    6. }

    因为我的Presenter需要等到运行的时候才会知道是哪个,所以使用泛型P代表

    创建具体的Presenter工厂类,在静态方法findClass中,通过传入的Activity获得Activity的注解,并通过注解获得相应的presenter的Class

    在createPresenter方法中,通过presenter的Class反射生成presenter对象

    1. class PresenterFactory<P>() :IPresenterFactory

      {

    2. private var presenterKClass :KClass<*> ?=null
    3. constructor(presenterKClass :KClass<*>): this(){
    4. this.presenterKClass =presenterKClass
    5. }
    6. companion object{
    7. fun

      findClass(viewClass:Class<*>) : PresenterFactory

      {

    8. val annotation = viewClass.getAnnotation(Request::class.java)
    9. val value:KClass<*> =annotation.value
    10. return PresenterFactory(value)
    11. }
    12. }
    13. override fun createPresenter(): P {
    14. return presenterKClass?.java!!.newInstance() as P
    15. }
    16. }

    创建一个BasePresenter,实现IPresenter接口,将具体的View层的实例传过来。因为不知道具体的View是哪一个,所以使用泛型T表示

    1. abstract class BasePresenter<T> :IPresenter{
    2. protected var mView: @UnsafeVariance T? = null
    3. fun attachViewCompont(view: T) {
    4. mView = view
    5. }
    6. fun detechViewCompont() {
    7. mView = null
    8. }
    9. abstract fun setListeners()
    10. }

    为了实现设计模式的单一性原则,我们增加一个工厂类的代理类,来控制presenter的创建,已及view的绑定等操作:

    1. class PresenterDelegate<P,V>() where P:BasePresenter,V:IView {
    2. private var presenterFactory :IPresenterFactory

      ?=null

    3. private var presenter :P ?=null
    4. constructor(presenterFactory :IPresenterFactory

      ):this(){

    5. this.presenterFactory =presenterFactory
    6. }
    7. open fun getPresenter():P{
    8. if(presenter!=null){
    9. return presenter!!
    10. }
    11. if (presenterFactory != null) {
    12. if (presenter == null) {
    13. presenter = presenterFactory?.createPresenter()
    14. }
    15. }
    16. return presenter!!
    17. }
    18. open fun setPresenter(presenter: P) {
    19. this.presenter = presenter
    20. }
    21. open fun bindViewCompont(view: IView) {
    22. if (presenter == null) {
    23. getPresenter()
    24. }
    25. if (presenter != null) {
    26. presenter!!.attachViewCompont(view as V)
    27. }
    28. }
    29. open fun unbindViewCompont() {
    30. if (presenter != null) {
    31. presenter!!.detechViewCompont()
    32. }
    33. }
    34. }

    创建一个BaseActivity,继承AppCompatActivity实现IView接口,在BaseActivity中,通过创建工厂类的装饰类,创建具体的P层,并将P层和View层绑定

    1. abstract class BaseActivity<P,V> :AppCompatActivity(),IView where P:BasePresenter,V:IView{
    2. private var presenterDelegate = PresenterDelegate(PresenterFactory.findClass(javaClass))
    3. protected val mViews = SparseArray()
    4. protected var rootView: View? = null
    5. protected var mDecorView: View? = null
    6. open fun bindView(id: Int): T? {
    7. var view: T? = mViews[id] as T
    8. if (view == null) {
    9. view = rootView?.findViewById(id)
    10. mViews.put(id, view)
    11. }
    12. return view
    13. }
    14. override fun getContext(): Context? {
    15. return this
    16. }
    17. override fun getRootViews(): View? {
    18. return rootView
    19. }
    20. override fun getView(id: Int): T {
    21. return bindView(id) as T
    22. }
    23. override fun onCreate(savedInstanceState: Bundle?) {
    24. super.onCreate(savedInstanceState)
    25. presenterDelegate.bindViewCompont(this)
    26. rootView = layoutInflater.inflate(getLayoutId(), null, false)
    27. setContentView(rootView)
    28. initFields()
    29. bindEventListener()
    30. getPresenter().onCreate(savedInstanceState,this)
    31. getPresenter().setListeners()
    32. mDecorView = window.decorView
    33. }
    34. override fun onStart() {
    35. super.onStart()
    36. getPresenter().onStart()
    37. }
    38. override fun onRestart() {
    39. super.onRestart()
    40. getPresenter().onRestart()
    41. }
    42. override fun onResume() {
    43. super.onResume()
    44. getPresenter().onResume()
    45. }
    46. override fun onPause() {
    47. super.onPause()
    48. getPresenter().onPause()
    49. }
    50. override fun onStop() {
    51. super.onStop()
    52. getPresenter().onStop()
    53. }
    54. override fun onDestroy() {
    55. getPresenter().onDestroy()
    56. presenterDelegate.unbindViewCompont()
    57. super.onDestroy()
    58. }
    59. protected open fun onSaveInstanceState(outState: Bundle?) {
    60. super.onSaveInstanceState(outState!!)
    61. getPresenter().onSaveInstanceState(outState!!)
    62. }
    63. protected open fun onRestoreInstanceState(savedInstanceState: Bundle?) {
    64. super.onRestoreInstanceState(savedInstanceState!!)
    65. getPresenter().onRestoreInstanceState(savedInstanceState!!)
    66. }
    67. override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    68. super.onActivityResult(requestCode, resultCode, data)
    69. getPresenter().onActivityResult(requestCode, resultCode, data!!)
    70. }
    71. /**
    72. * 返回layout 布局文件的id
    73. *
    74. * @return
    75. */
    76. abstract fun getLayoutId(): Int
    77. /**
    78. * 初始化其他属性
    79. */
    80. abstract fun initFields()
    81. /**
    82. * 设置监听
    83. */
    84. abstract fun bindEventListener()
    85. open fun getPresenter(): P {
    86. return presenterDelegate.getPresenter()
    87. }
    88. open fun setPresenter(presenter: P) {
    89. presenterDelegate.setPresenter(presenter)
    90. }
    91. }

    这样一个mvp架构就搭建完毕了,下面看看使用:

    1. interface ITestView :IView {
    2. fun setContent(string: String)
    3. }

    Module层:

    1. class TestModule :IModule{
    2. fun doNetWork(){
    3. println("网络请求")
    4. }
    5. }

    Presenter层:

    1. class TestPresenter: BasePresenter<ITestView>() {
    2. var module:TestModule? =null
    3. override fun setListeners() {
    4. }
    5. override fun onCreate(savedInstanceState: Bundle?, mContext: Context?) {
    6. module =TestModule()
    7. }
    8. override fun onResume() {
    9. module?.doNetWork()
    10. mView?.setContent("222222222")
    11. }
    12. override fun onStart() {
    13. }
    14. override fun onRestart() {
    15. }
    16. override fun onPause() {
    17. }
    18. override fun onStop() {
    19. }
    20. override fun onDestroy() {
    21. }
    22. override fun onSaveInstanceState(outState: Bundle) {
    23. }
    24. override fun onRestoreInstanceState(savedInstanceState: Bundle) {
    25. }
    26. override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent) {
    27. }
    28. }

    View层:

    1. @Request(TestPresenter::class)
    2. class TestActivity :BaseActivity<TestPresenter,ITestView>(),ITestView {
    3. var textView:TextView?=null
    4. override fun getLayoutId(): Int {
    5. return R.layout.activity_main
    6. }
    7. override fun initFields() {
    8. textView =findViewById(R.id.txt)
    9. }
    10. override fun bindEventListener() {
    11. }
    12. override fun setContent(string: String) {
    13. textView?.text =string
    14. }
    15. override fun getActivity(): Activity? {
    16. return this
    17. }
    18. override fun getFragment(): Fragment? {
    19. return null
    20. }
    21. }

  • 相关阅读:
    知识蒸馏6: yolov5知识蒸馏训练
    分析智能平台VMware Greenplum 7 正式发布!
    带团队后的日常思考(八)
    Packet Tracer - 配置多区域 OSPFv2
    【QT】QTableView或QTableWidget 搭配QLineEdit实现数据的搜索显示
    1、深入了解MySQL中内部组件架构(连接器,查询缓存,分析器,优化器,执行器等)
    IDEA中使用注解Test
    C++:容器list的介绍及使用
    NumPy 数组应用初探
    单据架构—实现页面可配置化
  • 原文地址:https://blog.csdn.net/y2653904/article/details/133266373