Android developers, heads up! The future of Android applications architecture is here and you better embrace it now, or else be forgotten by the history! Hmm, to be honest, this reads a bit more bombastic than I intended, but I think I’ll leave it like that for now. You can decide for yourself if such an excitement on my part was justified after you read this post.
So, what’s all this about? Well, I watched a talk by Netflix’s Juliano Moraes from the latest Droidcon NYC and found it amazing. In this talk, Juliano showed Netflix Android application’s architecture and explained how it supports their large-scale AB testing strategy.
See, it’s usually impossible to draw a straight connection between software architecture and business advantage (and it’s not that nobody tried), but seems like it’s what happened at Netflix. AB testing allows you to find the best implementation for a feature (in terms of real business KPIs) out of set of potential solutions, and, as such, it’s a high-impact business value multiplier. Netflix folks can quickly explain how their architecture enables simple and safe AB testing, which means that it’s a thing.
So, let’s discuss this architecture in details and see what can we learn from Netflix.
Netflix Android Architecture
That’s how Juliano summarized the core feature of Netflix Android architecture:
One thing that is a little bit controversial that I’m going to say is: the Fragment should not be your View. The Fragment should take care of the lifecycle of your application.
This statement is indeed a bit controversial in Android community today because most of the examples of MVP, MVC and MVVM architectural patterns designate Activities and Fragments as MVx views. Netflix took a very different route with their interpretation of MVP.
Let’s review their approach in details, one component at a time.
The view in Netflix architecture is a standalone Java (or Kotlin) class which doesn’t(!) extend Android View. It takes care of XML inflation and manages the underlying Andorid Views, but it doesn’t expose any of these details to the outside world.
From outside, the view looks like a regular class that has a bunch of declarative methods:
However, even though the view abstracts out all UI related details, it still should be able to notify the outside world about user interactions with UI elements. Netflix folks decided to use publish-subscribe pattern to support this requirement. More specifically, they implemented a simple event bus using RxJava. Whenever user interactions occur, the view posts specific events which correspond to specific types of user interactions to that event bus.
The view can also take care of animations and other UI stuff, but that’s where its responsibilities end. It doesn’t contain any presentation or business logic.
Each view in Netflix architecture comes bundled with a dedicated presenter. As far as I understand, they enforce 1-to-1 relationship between presenters and views.
Presenters have references to views and call their methods whenever the state changes and UI needs to be updated accordingly. To monitor the state, presenters subscribe to event bus and wait for relevant state change events:
One interesting implementation choice Netflix made is that the events emitted by views are not the same events that affect the presenters. It’s unusual because the standard approach is for presenters to handle all notifications from their respective views. This point worth discussing in more details and I’ll get back to it a bit later.
So, the view emits events which aren’t consumed by the presenter and the presenter consumes events which aren’t emitted by the view. Who emits the events for the presenter and consumes view’s events then?
Well, it’s Fragment.
In Netflix architecture, Fragment resides at the root of “screen” hierarchy and contains one or more presenter-view pairs. It is the one responsible for receiving events from views, processing them and then notifying the presenters about state changes:
As I already said, it’s an odd implementation because, usually, presenters and views communicate directly and don’t need additional third-party as a proxy. So, why Netflix chose to do it this way?
My guess is that they were forced to do that because they have big part of presentation and business logic in their Fragments. I don’t mean that their Fragments contain thousands of lines of code; that would be surprising given the fact that Juliano repeatedly mentioned their emphasis on unit testing. What I mean is that Fragments are the ones who have references to e.g. use case objects and invoke them in response to user interactions.
But why would they do it that way instead of putting this logic in presenters? Well, consider the following example.
Let’s say they want to AB test five different implementations of playback controls. That would amount to five different view-presenter pairs in Netflix architecture. If the presenter would be responsible for initializing the playback, then they’d have to duplicate that logic in five different presenters. Not good. The simple solution to this problem is to make sure that all user interaction events reach to the root of screen hierarchy and put the logic there. This way they can replace view-presenter pairs as they wish while not being concerned with logic duplication.
Or, maybe, Fragment’s involvement is related to the fact that they want to broadcast events from each view to all the presenters, so Fragment functions as a central messaging hub.
Again, these are just my guesses. Maybe the real reason is completely different.
But then, given that Fragment clearly participates in the flow, the question becomes: “is this MVP at all”? Yes, it is. See, good presentation layer architecture should allow for easy reuse and nesting of UI and functional logic. Including nested presenters.
That’s exactly what Netflix folks implemented: nested presenters. They have Fragment as the “root” presenter for each screen and then nest multiple additional presenters in it. The reason you don’t see this technique used too much (or ever) in Android is because you simply can’t do that if you use Activities as views. And even though nesting of presenters kind of possible with Fragments as views, it’s total mess.
However, once you switch gears and stop treating Activities and Fragments as views, a whole new world of architectural opportunities opens up for you.
Activities and Fragments are not MVx Views
At this point you might be wondering why I discuss Netflix Android architecture with such a confidence. After all, it probably took them years until they arrived at this implementation and there is probably much more to it than Juliano was able to share in his talk. So, let me explain.
Netflix discovered that Fragments shouldn’t be views. That’s interesting and controversial point, but, if you watch the talk, you’ll notice that Juliano didn’t explain why that’s the case. He just stated that they discovered this feature and moved on, which is totally understandable because it would take him an entire hour to explain this point alone and it obviously wasn’t his goal.
But it was my exact goal at Droidcon Berlin this year.
In this talk I explained why activities and fragments aren’t MVx views and the alternative I proposed are the same views that you see in Netflix architecture. Moreover, I gave a similar talk at Droidcon Tel-Aviv in 2017 and there I specifically discussed how this approach makes AB testing easier. But even that isn’t the whole picture. If you scroll all the way down on the main page of this blog, you’ll discover that the very first post that I wrote is titled Activities in Android are not UI Elements. It was the moment that I extracted standalone view from Activity that I decided to start this blog because I wanted to share this approach with other developers.
All in all, Netflix architecture isn’t new to me because I’ve been using and promoting it for a very long time.
The Past of Android Applications Architecture
I really want to get to the future of Android applications architecture, but the picture will be incomplete without discussion of the past. Therefore, let me share with you some historical facts.
In his talk, Juliano mentioned that Netflix got the idea of views emitting user interaction events from MVI. That’s alright, but let’s give the credit where it’s due and avoid further terminology salad. “Intent” had a specific meaning in Android since day one, and the practice of sending events from MVx views is much older than MVI (and even older than Android itself). In fact, the earliest Android MVC tutorial that I’m aware of shows this exact technique (though it calls these events “messages” because the implementation used Android’s Handler). So, these aren’t “intents”. These are just events posted to event bus when user interactions occur.
I also wouldn’t like you to think that I realized that Activities and Fragments aren’t MVx views on my own, or that Netflix were the first ones. The earliest mention of this architectural breakthrough (and I’m being dead serious when I call it that) dates back to 2012.
So, the foundation of this architecture was developed by the community over a very long period of time and it’s not really new. Initially it was called MVC, but today it’s called MVP in most cases. Both names are applicable because neither MVC nor MVP have standard, universally agreed definitions.
The Future of Android Applications Architecture
For the past several years I’ve been absolutely confident that the kind of MVx that Netflix adopted is the future of Android architecture. This confidence stemmed from my own experience with this approach and the fact that other developers, who picked it from this blog, provided outstanding feedbacks. In addition, since I started attending conferences I constantly meet developers who came up with variations of the same architecture. As far as I can tell, this architectural pattern re-discovered times and again because it’s the natural structure for Android applications.
However, I knew that it will be very hard to convince the community to adopt this architecture, especially given that Google promoted completely different approaches (more on that later). Therefore, I waited for a major player in the industry to adopt it. I was absolutely confident that it will happen, but I couldn’t even dream that Netflix will be the first. To explain why I’m so excited about Netflix specifically, let’s talk about Netflix engineering for a moment.
As far as I know, Netflix developers aren’t very active in Android community. However, on a bigger scale, Netflix is one of the leading software excellence houses in the world. One could argue that Netflix validated micro-services architecture and made it mainstream. Netflix was also one of the earliest big AWS customers that went all-in on cloud, so they validated the cloud as well. In addition, they constantly share experience, knowledge and tools related to distributed systems reliability. You simply can’t research this topic without constantly running into their content and tools.
And, even though I don’t use it personally, let’s not forget that these were Netflix engineers who gave the world RxJava.
If I’d need to draw an analogy, I’d say that Netflix to the greater software community is like Square to Android developers. That’s why I’m super excited that it was Netflix who came up with this architecture. You just can’t ask for more validation than that.
Google will be slow to catch up
Now let’s address the elephant in the room. I can say whatever I want and Netflix can adopt any kind of architecture, but, as long as Google promotes different practices, most Android developers will use the official approaches even if they are inferior.
Unfortunately, as far as I can say, Google will not catch up any time soon.
Surprisingly, googlers already know that Activities and Fragments aren’t views. During Google IO16 Adam Powell explicitly said that Fragments aren’t views, but ? in MV?. More recently, Ian Lake stated that Fragments are view-controllers and not views. However, even though they seem to acknowledge this absolutely crucial point in theory, it doesn’t make it into practice. The official Android architecture blueprints still promote weird approaches where Fragments are views. The official Google IO18 application, which was rewritten from scratch to demonstrate “best practices”, uses Fragments in the same way. This inability to connect the dots is really strange.
As I mentioned, most of the concepts incorporated in Netflix architecture aren’t new. The community distilled this stuff long before Google jumped in with DataBinding and “architecture” components. In my estimation, if Google wouldn’t interfere with community efforts during the past years, Netflix-style architecture would become one of the standards for Android development. But Google did interfere, and there is no reason to assume that this interference will stop in the near future.
Therefore, Android developers who want to use the best architectural patterns to write clean and maintainable applications will need to make a tough choice.
It’s official – the best presentation layer architectural pattern for Android has been validated by Netflix. I can’t imagine any more validation than that.
The architecture I’m talking about isn’t some overhyped “the hottest architecture of this season”. It was evolved by different members of Android community over a course of many years and its origins can be traced as far back in time as 2010. The fact that different developers independently arrive at similar implementations times and again shows that these are the natural abstractions for Android development.
So, the past and the future of Android architecture have finally converged. Big thanks to Netflix engineers for making this happen.
As usual, thanks for reading and you can leave your comments and questions below.
Now a little bit of self-promotion if you don’t mind.
If you’ve read so far, you might be interested in actually seeing this architecture in practice. In addition, even though Netflix did a great job, there are still some bits that can be improved. For example, their granularity of reuse is presenter+view, while it actually makes a lot of sense to make the views reusable and composable on their own. In addition, this architectural pattern, which is absolutely outstanding on its own, gets a serious boost when combined with proper dependency injection.
I discussed all these topics, and many others, in my latest course: Android Applications Architecture. It’s the most comprehensive and advanced resource about architecture of Android apps. If you’ve read so far, I strongly recommend that you visit the course page and read the reviews. Cheers.