Android MVP+Dagger2实现

前言

项目有更新(解耦),具体使用参照github项目,地址:https://github.com/wz1509/Base-Mvp,欢迎star/fork


  • 2018-08-27 加入dagger2的支持,M与P V与P 解耦

简介

对于一个应用而言我们需要对它抽象出各个层面,而在MVP架构中它将UI界面和数据进行隔离,所以我们的应用也就分为三个层次。

  • View:对于V层也是视图层,在View层中只负责对数据的展示,提供友好的界面与用户进行交互。在Android开发中通常将Activity或者Fragment作为V层。
  • Model:M层负责访问数据。数据可以是远端的Server API,本地数据库或者SharedPreference等。
  • Presenter:P层是连接V和M的桥梁。在MVP架构中M与V无法直接进行交互。所以在P层它会从M层获得所需要的数据,进行一些适当的处理后交由V层进行显示。这样通过P将V与M进行隔离,使得V和M之间不存在耦合,同时也将业务逻辑从V中抽离。

下面通过MVP结构图来看一下MVP中各个层次之间的关系。

  在MVP架构中将这三层分别抽象到各自的接口当中。通过接口将层次之间进行隔离,而Presenter对View和Model的相互依赖也是依赖于各自的接口。这点符合了接口隔离原则,也正是面向接口编程。在Presenter层中包含了一个View接口,并且依赖于Model接口,从而将Model层与View层联系在一起。而对于View层会持有一个Presenter成员变量并且只保留对Presenter接口的调用,具体业务逻辑全部交由Presenter接口实现类中处理。

架构

Base类

BaseContract

interface BaseContract {

    /**
     * View通用方法
     */
    interface View {

        fun showLoading()

        fun hideLoading()

        fun onApiFail(msg: String)
    }

    /**
     * Presenter通用方法
     */
    interface Presenter: LifecycleObserver {

        @OnLifecycleEvent(Lifecycle.Event.ON_DESTROY)
        fun detachView()
    }

    interface Model {

        fun onDestroy()
    }
}

这里的三个接口作为项目的通用接口。

BaseModel

abstract class BaseModel : BaseContract.Model {

    val disposables: CompositeDisposable by lazy(LazyThreadSafetyMode.NONE) {
        CompositeDisposable()
    }

    val apiService: ApiService by lazy(LazyThreadSafetyMode.NONE) {
        AppApplication.appApplication.applicationComponent.getApiService()
    }

    override fun onDestroy() = disposables.clear()
}

实现BaseContract.Model接口onDestroy()方法,用于取消网络。apiService 懒加载实例化是Application中 dagger2 注入的,具体 dagger2用法这里不做叙述。

BasePresenter

abstract class BasePresenter(private var view: BaseContract.View?,
                             private val model: BaseContract.Model) : BaseContract.Presenter {

    override fun detachView() {
        model.onDestroy()
        view = null
    }
}

BasePresenter继承于BaseContract.Presenter实现detachView()方法,用于销毁view和取消网络。这里BaseContract.Presenter接口是继承LifecycleObserver接口,如果在activity/fragment中添加了观察者对象 lifecycle.addObserver(presenter) ,那么presenter是具有activity/fragment生命周期变化的回调通知。

BaseMvpActivity

abstract class BaseMvpActivity

.Presenter> : BaseActivity(), BaseContract.View { @Inject lateinit var presenter: P private val dialog by lazy { AlertDialog.Builder(this).create() } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) injectPresenter() lifecycle.addObserver(presenter) } fun getActivityComponent(view: ViewModule): ActivityComponent { return DaggerActivityComponent.builder() .applicationComponent(AppApplication.get(this).applicationComponent) .activityModule(ActivityModule(this)) .modelModule(ModelModule()) .viewModule(view) .build() } override fun showLoading() { dialog.setTitle("title") dialog.setMessage("加载中...") dialog.show() } override fun hideLoading() { dialog.dismiss() } abstract fun injectPresenter() }

BaseMvpActivity用于提供injectPresenter()方法用于实例化presenter,onCreate()中添加观察者,用于观察生命周期变化。这里getActivityComponent(view: ViewModule)方法是用dagger2注入model和injectPresenter()方法中注入View。

使用

MainContract

interface MainContract {

    interface View : BaseContract.View {

        fun onResult(result: String)
    }

    /**
     * 如果后面继承了 BasePresenter,这里就不需要重复继承 BaseContract.Presenter
     */
    interface Presenter {

        fun getToday()
    }

    interface Model : BaseContract.Model {

        fun getToday(callback: ResultCallBack)
    }
}

MainModel

class MainModel : BaseModel(), MainContract.Model {

    override fun getToday(callback: ResultCallBack<String>) {
        apiService.getToday()
                .doOnSubscribe { disposables.add(it) } // 将disposable添加到容器中
                .compose(RxHelper.ioMain())            // 这里是io-main线程切换
                .subscribe({
                    val jsonElement = JsonParser().parse(it.string())
                    val result = GsonBuilder().setPrettyPrinting().create().toJson(jsonElement)
                    callback.onSuccess(result)
                }, {
                    callback.onFail(ApiCodeException.checkException(it))
                })
    }
}

ModelModule

@Module
class ModelModule {

    @Provides
    fun provideMainModel(): MainContract.Model = MainModel()
}

ViewModule

@Module
class ViewModule(private val mainView: MainContract.View){

    @Provides
    fun provideMainView() = mainView
}

MainPresenter

class MainPresenter @Inject constructor(
        private var model: MainContract.Model, private var view: MainContract.View
) : BasePresenter(view, model), MainContract.Presenter {

    override fun getToday() {
        view.showLoading()
        model.getToday(object : ResultCallBack.SimpleResultCallBack<String>() {
            override fun onSuccess(data: String) {
                view.onResult(data)
                view.hideLoading()
            }

            override fun onFail(errorMsg: String) {
                view.onApiFail(errorMsg)
                view.hideLoading()
            }
        })
    }
}

MainActivity

class MainActivity : BaseMvpActivity<MainPresenter>(), MainContract.View {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        request_network.setOnClickListener {
            presenter.getToday()
        }
        to_fragment.setOnClickListener {
            // this.finish()
            startActivity(Intent(this@MainActivity, FrameActivity::class.java))
        }
    }

    override fun injectPresenter() {
        getActivityComponent(ViewModule(this))
                .inject(this)
    }

    override fun onResult(result: String) {
        content_text.text = result
    }

    override fun onApiFail(msg: String) {
        content_text.text = msg
    }
}

总结

  通过MVP架构的使用可以看出对于各个层次之间的职责更加单一清晰,同时也很大程度上降低了代码的耦合度。但任何架构都有利有弊,MVP模式在使各层职责单一的条件下项目中类的数量也增多了,由于大部分都是调用接口使得调试中跳转往往跳转到接口中,而接口实现类的代码却看不到,增加了调试负担。最近google新出的Jetpack架构模式也可以试试。


项目地址:https://github.com/wz1509/Base-Mvp
喜欢的话 给个star支持吧 (=・ω・=)

你可能感兴趣的:(Android,开源)