A Refined Approach to MVC in Android Part 5 — Applying to Lists and Fragments
From Part 1 up to Part 4 we have come a long way and converted the architecture of our StackOverflow client app from the legacy approach in which the activities are rigidly coupled with their views to a flexible and highly unit testable MVC architecture.
In this chapter we will see that the approach to MVC we have used is naturally in tune with how the Android framework itself is built. We will see how the same approach we have used in the two Activities of our application can be easily applied to Fragments, Lists and Dialogs.
Applying to RecyclerView List
In our study application, the view of QuestionsListActivity consists of RecyclerView that is backed by the following adapter:
We can create an implementation of BaseObservableMvcView for item_questions_list.xml and extract all the view logic from the adapter as follows:
From this we can then extract a contract for the list item view which is as follows:
We extend BaseObservableMvcView and specify QuestionListItemListener as the observer so that we call listen for user input which is in this case when a user clicks on a list item. We then let extend QuestionsListItemMvcView in QuestionsListItemMvcViewImpl as follows:
Since QuestionsListItemMvcView extends from classes in our MVC view class hierarchy, it also inherits the convenience methods like setRootView(), getRootView() and findViewById().
We then expose a method in MvcViewFactory that will provide QuestionsListItemMvcView:
And then we refactor QuestionsAdapter accordingly:
In QuestionsAdapter we implement QuestionsListItemListener and simply propagate the call to OnItemClickListener. The ViewHolder is now simply a container for our MvcView.
To complete the change, since we changed the constructor of QuestionAdapter to take in MvcViewFactory, we also need to make the corresponding changes to QuestionsListMvcViewImpl as follows :
Since we have also changed the constructor of QuestionsListMvcViewImpl we also need to make the corresponding change inside MvcViewFactory as follows:
Since the constructor of QuestionsListMvcViewImpl now takes in MvcViewFactory as a parameter, we use the “this” keyword pass in the current instance of MvcViewFactory.
This completes the abstraction of the list item view. We can now create a new implementation of QuestionsListItemViewMvc that has new design and simply swap it with QuestionsListItemMvcViewImpl without having to touch QuestionsAdapter or QuestionsListMvcViewImpl. The only change that we would have to make is in MvcViewFactory under the getQuestionsListItemMvcView() method.
Fragments
I will not go into much detail regarding how we can apply our MVC approach to fragments but will just give a glance of how easy it is. If for example we wanted to convert QuestionsListActivty into a Fragment it will be like as follows:
The important thing to note is that now we pass in the container parameter of onCreateView() as the parent argument to the getQuestionsListMvcView() method.
In the same manner you can apply this MVC approach to dialogs that extend the DialogFragment class. You can create a “dialog manager” class (just like ToastManager ;)) that will handle your dialogs. This offer you the same powerful and flexibility by being able to manage all the dialogs shown in your applications in one place.
The most important method that in our MVC view class hierarchy that enables this approach to be integrated easily with the android framework is getRootView() defined in MvcView, which is the parent class of our Mvc view hierarchy.
The final code state of the application at this point can be found here.
Conclusion
In this series article, saw how we can use object-oriented programming techniques to create a loosely coupled architecture that his highly testable and provides great flexibility. Also created a suit of re-usable classes that make implementing MVC methodical and consequently easier.
The overall quality of our applications architecture depends on how best we manage the complexity of the code. A good way to manage complexity is breaking down the structure of our architecture into smaller loosely coupled components that have as few responsibilities as possible. This gives us the indispensable power of being able to deal with each component in isolation.
Although developing our applications in this way might seem to involve a lot of effort and overhead, when building non trivial apps there is really no substitute to spending due effort to make sure that the architecture of our applications are testable, flexible and easily maintainable. This will save us a lot of time, effort and money in the long run as our applications increase in complexity.
This brings us to the end of this multipart article. Thanks for reading!
**PS — If you have a question, don’t hesitate to reach out in the comment section or at tapsmuzira@gmail.com.