Should I pass a View to a Presenter's constructor?
Tags: discuss, android, kotlin, mvp
Published: 2018-11-05 04:31:29

---
title: Should I pass a View to a Presenter's constructor?
published: true
description: 
tags: discuss, android, kotlin, mvp
cover_image: https://thepracticaldev.s3.amazonaws.com/i/jxux21la8h9i0alt41m3.jpeg
---

<center>Cover image by [Ben White](https://unsplash.com/@benwhitephotography) from [Unsplash](https://unsplash.com)</center>

---

I've seen multiple variations of how to implement the MVP (Model-View-Presenter) pattern on Android and one of the things that got my attention was that the way the Presenter's View is set or initialized varies from author to author.

Here's an example of what I'm saying:

Let's say we have a `LoginActivity`. In it's `onCreate` method, we will have to set the Presenter and also pass in a reference to the `LoginActivity` so it can manipulate it.

But, before we do that we should make our `LoginActivity` implement an interface, let's call it `LoginView`, which will be the Type of the object our `LoginPresenter` will use.

## Presenter Example 1

First, we make a base presenter interface that will be used by every other specific presenter class:

```kotlin
interface Presenter<V> {
    fun attach(view: V)
    fun detach()
}
```

Then, we implement it in our `LoginPresenter`:

```kotlin
class LoginPresenter : Presenter<LoginView> {

    private var view: LoginView? = null

    override fun attach(view: LoginView) {
        this.view = view
    }

    override fun detach() {
        view = null
    }

    // ...

}
```

And since we have our `attach()` and `detach()` methods, our `LoginActivity` would look like this:

```kotlin

class LoginActivity : AppCompatActivity(), LoginView {

    private lateinit var presenter: Presenter<LoginView>

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        presenter = LoginPresenter()
        presenter.attach(this)
    }

    override fun onDestroy() {
        super.onDestroy()
        presenter.detach()
    }

    // ...
}

```

Now, since I'm using Kotlin for this example we can make use of the `apply` method and make it go from this:

```kotlin
presenter = LoginPresenter()
presenter.attach(this)
```

To:

```kotlin
presenter = LoginPresenter().apply { attach(this@LoginActivity) }
```

Which helps, but still...

My problem with this approach is that if for whatever reason the developer forgets to use the `attach()` method will face unexpected results that can lead to a frustrating set of minutes/hours trying to find the bug.

_Which may or may not be me a few days ago 😅_

So, in order to prevent this, I thought it would be better to do the following:

## Presenter Example 2

We can remove the `attach()` method from the `Presenter` interface, which would leave us with:

```kotlin
interface Presenter<V> {
    fun detach()
}
```

And since the `V` is not being used, we can also remove it.

```kotlin
interface Presenter {
    fun detach()
}
```

Now, I would like to rename this interface with the `-able` naming convention, which would be:

```kotlin
interface Detachable {
    fun detach()
}
```

Examples of interfaces that use this naming convention are: `Runnable`, `Serializable`, `Readable` and `Parceable`.

This change would also require us to change our `LoginPresenter` from this:

```kotlin
class LoginPresenter : Presenter<LoginView> {

    private var view: LoginView? = null

    override fun attach(view: LoginView) {
        this.view = view
    }

    override fun detach() {
        view = null
    }

    // ...

}
```

To:

```kotlin
class LoginPresenter(private var view: LoginView?) : Detachable {

    override fun detach() {
        this.view = null
    }

}
```

So, now all we have left to do is to change our `LoginActivity` code from this:

```kotlin
presenter = LoginPresenter()
presenter.attach(this)
```

Or this:

```kotlin
presenter = LoginPresenter().apply { attach(this@LoginActivity) }
```

To:

```kotlin
presenter = LoginPresenter(this)
```

So our entire `LoginActivity` class would be:

```kotlin
class LoginActivity : AppCompatActivity(), LoginView {

    private lateinit var presenter: LoginPresenter

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        presenter = LoginPresenter(this)
    }

    override fun onDestroy() {
        super.onDestroy()
        presenter.detach()
    }

    // ...
}
```

And for those that are not fan of `lateinit` properties:

```kotlin
class LoginActivity : AppCompatActivity(), LoginView {

    private val presenter = LoginPresenter(this)

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

    override fun onDestroy() {
        super.onDestroy()
        presenter.detach()
    }

    // ...
}
```

Now you we can all make sure that our `LoginPresenter` will always be in a _valid state_ when we use it.

---

I may have overlooked something with the Example 2 approach, which is why I would like to know your thoughts :)