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中各个层次之间的关系。
结构图.jpg

  在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<P : BaseContract.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<String>)
    }
}

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支持吧 (=・ω・=)

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java Android MVP技术栈是一种在Android开发中常用的架构模式,它将应用程序分为三个主要的组件:Model(模型)、View(视图)和Presenter(展示者)。这种架构模式的目的是将业务逻辑与界面逻辑分离,使代码更加清晰、可维护和可测试。 具体来说,Java Android MVP技术栈的组件包括: 1. Model(模型):负责处理数据的获取、存储和处理。它可以是从网络获取数据的API接口、数据库操作类或其他数据源。 2. View(视图):负责展示数据和与用户进行交互。它可以是Activity、Fragment或自定义的View。 3. Presenter(展示者):作为View和Model之间的中间人,负责处理业务逻辑和协调View和Model之间的通信。它从Model获取数据,并将数据传递给View进行展示,同时也接收来自View的用户交互事件,并根据需要更新Model。 通过使用MVP技术栈,可以实现以下优点: 1. 分离关注点:将业务逻辑和界面逻辑分离,使代码更加清晰、易于理解和维护。 2. 可测试性:Presenter负责处理业务逻辑,可以通过单元测试来验证其正确性,而View则可以通过UI测试来验证其交互行为。 3. 可扩展性:由于各个组件之间的解耦,可以更容易地对应用程序进行扩展和修改。 4. 可复用性:Presenter和Model可以在不同的View中重用,提高代码的复用性。 在实际开发中,可以使用第三方库来帮助实现MVP架构,例如Google官方推荐的Dagger2用于依赖注入、RxJava用于异步操作和事件处理、Retrofit用于网络请求等。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值