Refactoring an Activity into MVP with Kotlin

Drawing is not my best 🙄

A short time ago I created a simple Activity for a colleague to give me a hand with an easy feature that displays a list of information. He wrote the feature in the same Activity, as traditionally it’s been done, not using any MVP design, so I’m going to refactor this code step by step.

Note 1️⃣: I’m following Uncle Bob Clean Architecture so a feature should be divided in ui , domain and data . This article treats the ui part which will be divided in model ,view and presenter

Note 2️⃣: We’re not going to show any layout here as it’s not relevant with the topic.

Code I gave to my colleague

I like creating companion objects to start activities from outside and remove inner logic externally.

Feature done by my colleague

I’m going to show the code it was given to me which is 100% working:

First of all, I have to agree that using ListView is a bad option having RecyclerView from the support library, so I’ll change ListView to RecyclerView and its respective Adapter💁🏻‍. I’ll be showing only the code that regards the SimpleListActivity but the same procedure is done with the RecyclerView.Adapter and the RecyclerView.ViewHolder

First step is cleaning code and separating functionalities
Explained in another way, I want to separate the activity in simple tasks, for example: 
- If we configure a Toolbar we create a function specifically for that.
- If we set many click listeners, we group them in the same place.
- We will also remove also unnecessary code.
- We will pass the parameter pages to the Adapter . The Activity doesn’t have to know about it.
- We will separate the Adapter from the SimpleListActivity keeping them all in the same package simpleListActivity.ui.view

One of the reasons why MVP was created is to separate logic from the Activity and place them somewhere else. Now, if we pay attention to this SimpleListActivity it does basically:
-
Set OnClickListeners
- Loads a BannerImage
- Configures a RecyclerView
So our SimpleListActivity will just know about that, while the presenter will compute most of the logic

So far, the refactored code would look like this. This doesn’t have any MVP yet, don’t rush it! 🏃‍

Time to create the View Presenter

I call the View Presenter to the interface that will go with the SimpleListActivity and the one in charge of changing the views with really simple logic or with a logic that the Logic Presenter carries on. Let’s add an interface called SimpleListActivityViewPresenter insimpleList.ui.presenter

What is this activity changing in terms of VIEW?
-
It’s just refreshing views (related to RecyclerView and another layout)
- It’s loading a Banner Image
- It’s setting Click Listeners:
 .- When back is clicked
 .- When signIn is clicked
 .- When register is clicked

So those will be our functions in our ViewPresenter:

SimpleListActivityViewPresenter.kt

I created a getActivity() method to simply get the Context but it can be done in many ways

Time to create the Logic Presenter

I call the Logic Presenter to the interface and class that will be added as a variable that will compute the logic within the View Presenter Let’s add an interface called SimpleListActivityPresenter and a class called SimpleListActivityPresenterLogic in simpleList.ui.presenter

What logic are we using here?
First of all, every override function we use that has a logic should be added in the LogicPresenter, plus every single logic we compute, such as when back button is clicked.

The result should look like this:

SimpleListActivityPresenter.kt

SimpleListActivityPresenterLogic.kt

SimpleListActivity.kt

as you can see now, our SimpleListActivity has a short length, and it describes what it does (creates, resumes, loads banner, configure recyclerViews, and declares its views). The rest is done by the SimpleListActivityPresenter which carries on with the SimpleListActivityPresenterLogic to do all the “ugly” code. I believe it involves more code in different files, but it helps more to understand every single Activity and helps also to do UI testing.

Our MODEL

Unfortunately, for this example, the list is based only on String but that is already a native class, so the simpleList.ui.model would be empty in this case. If a more complicated object should be needed (for example for the Adapter) that model should go there, never a model coming from the server.

What do you think?