0

I have an Activity, a Presenter, and a Contract which both the Activity and the Presenter implement. The Activity will have some unique UI stuff, which must be called from within the Presenter. The Presenter must also be able to make a call to the Activity (e.g. sendBroadcast()) which takes advantage of the fact that an Activity is also a Context.

Here is my conundrum: If I pass Context to the Presenter, I lose access to the UI methods unique to the Activity; if I pass the Contract.View to the Presenter, I lose access to the methods that require Context. The only solutions I can think of are:

A) Pass both the Context AND the Contract.View to the Presenter (which will always be the same Object, i.e. the Activity) OR

B) Ditch the Design-by-Contract pattern altogether and just directly pass the Activity to the Presenter


Both seem like rally bad ideas...What is the recommended approach here? Below is a scaled down version of the code I am currently working with:

Activity.kt

class Activity: AppCompatActivity(), Contract.View {

    private lateinit var mPresenter: Contract.Presenter

    @BindView(R.id.textView)
    private lateinit var mTextView: TextView

    override fun onCreate(savedInstanceState: Bundle?) {
        // ...
        mPresenter = Presenter(this)
    }

    override fun updateText(text: String) {
        mTextView.text = text
    }

}

Presenter.kt

// Pass Context or Contract.View as parameter to constructor?
class Presenter(private val ???: ???): Contract.Presenter {

    fun discoverService() {
        val intent: Intent = // ...

        mContext.sendBroadcast(intent)
    }

    override fun setServiceCommInfo() {
        mView.updateText(Acquiring Data from Service...)
        // ...
    }

}

Contract.kt

interface Contract {

    interface View {
        updateText(text: String)
    }

    interface Presenter {
        setServiceCommInfo()
    }

}
1
  • So far I understand, the problem can be solved by a mixture of both strategy and decorator pattern.
    – Sambit
    Commented May 15, 2020 at 19:52

2 Answers 2

0

A. Passing both to presenter. I found it cleaner and more SOLID. But honestly, I'm using just java from the tags. Hope it was something!

0

I came up with a solution that's "less ugly" (ugly is a very subjective term) than the two I mentioned in my original post. Basically the idea here is to identify that

  1. mContext and Contract.View will always be the same object
  2. An object O is considered to be an instance of interface I if O implements I

Adding the following code to Presenter.kt will make it unnecessary to pass the same object twice:

class Presenter(private val mContext: Context): Contract.Presenter {

    private lateinit var mView: Contract.View

    init {
        if (mContext is Contract.View) mView = mContext
    }

}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.