Refactoring an Activity into MVP with Kotlin
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
data . This article treats the
ui part which will be divided in
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
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
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
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
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
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:
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
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:
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.
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?