简体   繁体   中英

In Android MVP, should a presenter return a value?

I try to learn MVP, I have some question to ask, should a presenter return a value?

something like this:

class MainPresenter : BasePresenter<MainContract.View>(), MainContract.Actions {
    override fun getProducts (id: Int): List<Product> {
        //...
        return products
    }
}

interface MainContract {
    interface Actions {
        fun getProducts(id: Int): List<Product>
    }
}

or like this:

class MainPresenter : BasePresenter<MainContract.View>(), MainContract.Actions {
    override fun getProducts (id: Int) {
        //...
        mvpView?.showProducts(products)
    }
}

interface MainContract {
    interface Actions {
        fun getProducts(id: Int)
    }

    interface View{
        fun showProducts(products: List<Product>)
    }
}

The first question we ask is, to whom should presenter return value? Who is interested in presenter values? Do we want to mess our business logic with view layer? Given that our business logic is inside the presenter itself, who else is interested in any data?

Definitely that's not our intention and diverts from MVP. We need to propagate the values through interfaces, usually View layer methods and pass them as arguments to other interested parties that reside in the view layer.

TL;DR: Option #2

This is an opinionated answer, but I'd usually try to to inject some sort of an abstract view reference to the presenter. Basically, an interface, where the actual implementation could be an activity, fragment, or a view, but for the presenter it would not matter. All it knows about, is the contract presented by the interface.

I tend to not return values from my presenters. I would inject another abstraction into the presenter that gets the products. We usually call them interactors. Its responsibility is to fetch from a repository on a background thread and deliver the result on the main. The classical way with a callback looks like this (but you should consider using kotlin coroutines instead, which would allow you to avoid the callback):

class MainPresenter(val interactor: MainInteractor) : BasePresenter<MainContract.View>(), MainContract.Actions, MainContract.Interactor.Callback {
    override fun getProduct (id: Int) {
        //...
        interactor.getProduct(product, this) // this is the callback
    }

    override fun onResult(result: Product) {
        mvpView?.showProduct(result)
    }
}

interface MainContract {
    interface Interactor {
        interface Callback<T> { fun onResult(result: T) }
        fun getProduct(id: Int, listener: Callback<Product>)
    }

    interface View{
        fun showProduct(product: Product)
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM