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.
View
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.
Presenter
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.
Fragment
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.
Conclusion
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 Architecture Masterclass. 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.
Any “in code” examples?
Hello Max,
You can read my series of articles about MVP and MVC in Android. There is a simple tutorial app there.
However, while these articles show the most important concepts, they’re a bit basic. Therefore, you can also browse the source code of the tutorial application for my Android architecture course. It’s more involved and demonstrates concepts like views nesting and extraction of unit-testable controllers.
Cheers.
https://github.com/julianomoraes/componentizationArch
Why wouldn’t the View interactions be passed to the presenter and then the presenter emit the events to the fragment, this way avoiding the View -> Fragment direct communication.
That would be possible, but I don’t see much benefit in comparison to their current implementation.
See, when you use event bus pattern the communicating entities don’t need to know about each other as long as they agree on the type of events being exchanged. Therefore, there is no view->Fragment direct communication per se. All communications through event bus are “indirect”.
There are benefits and drawbacks to using an event bus for such a communication.
I too switched to event bus for this type of communication in my project about three years ago. It looked very handy on the first sight. However, after working about a year with this approach, I realized that I prefer to have more explicit coupling in this area, so I switched to standard callbacks.
To be honest, I suspect that Netflix arch don’t really need event bus either, but that’s not a claim I would make without reviewing the actual code.
Hi Vasiliy!
I have followed your blog for some time (I came in by chance when looking for a MVC discussion in Android) and have even implemented an app based on your ideas (Activity and Fragments as controllers).
I am just curious: if you would design Android all over again how would you do it? You must surely have thought about it? This is clearly a too huge question but I am interested in how you think.
Hey Johan,
Wow, what a question! I didn’t think about how I’d design Android from scratch, but I thought a lot about various unfortunate decisions that were made. I’ll list three unfortunate choices from the top of my head:
Evidently, that’s not enough to describe how I’d design Android. To be honest, I’m not sure I know enough to even start answering this question. However, I’m sure that the above decisions contributed a lot to the state of Android framework today.
By the way, since you mentioned that you implemented an app using MVC and it’s related to this post, I’d be glad to hear your feedback as well. Honest feedback.
Hello Vasiliy!
I wrote you also on Twitter but I figured out that maybe here it would be a better context to ask you the question (no characters limitation 🙂 ).
I have a couple question for you:
What do you think of MVI architecture and do you think it would fit well in your template app that you’ve released on Github? Why? Why not? Would you do it?
Also since we are in the subject of MVI with this article too, would you say that the Netflix version of the architecture can be described as a fusion of your MVC and MVI?
I’m asking this because I heard a discussion on a famous podcast where one of the major proposer and supporter of the MVI architecture pattern was explaining the advantages of the latter and I was really intrigued by the “state” aspect of the architecture. Let me know what you think!
Hey Matt,
Interesting question. I’ll start with a disclaimer: I’ve never worked with MVI, so keep that in mind when reading the below answer.
I have mixed feelings about MVI. On the one hand, it contains some interesting concepts. On the other hand, there are some clear misunderstandings.
First of all, MVI (if we talk about what Hannes described here) is just MVP. As I wrote in this article, MVI’s “intent” is really just user interaction event. Since Intent is pre-existing and important class in Android, I doubt that “intent” is a better term than “event” or “user interaction event” to designate this concept. But even if you want to use the term “intent”, it’s surely not an architectural concept, but view’s implementation detail. Therefore, IMHO, the term MVI is unjustified and misleading.
So, MVI is just MVP where you implement the interaction between the view and the presenter in a specific way.
As for the concept of the “state”, I assume that you refer to the data structures that presenters bind to views (through render methods). Well, I agree that keeping UI’s state consistent might be a challenge, but I’m not sure that simply having a single “state” object that you bind to views automatically resolves the problem. For instance, looking at HomeViewState data structure that Hannes implemented here, it looks like you could still make a mistake and set all the flags to true. What would be view’s state then?
Looks like the only way to address this problem is to cover the logic with unit tests, but then I’m not sure that implementation details matter much. But, again, I don’t have hands on experience with unit testing MVI presenters…
So, these are my issues with MVI.
The interesting opportunity that arises from choosing this implementation of MVP is that of errors reporting. It sounds reasonable that if you can attach a full log of events to your crash reports, for example, then you’ll have easier time finding and fixing bugs. However, to understand whether this is a real advantage and whether it’s even practical, one would need to actually try that in production. I don’t have that experience.
So, these are my thoughts about MVI.
As for whether Netflix’s arch is a blend between “my” MVC and MVI, it’s hard to say without reviewing the code. For instance, from Juliano’s presentation I understood that presenters call simple methods on views, without using “view state” data structures. If that’s correct, then Netflix is pretty far from MVI.
Hope this helps.
IT is awesome ❤️❤️
Hey Vasiliy,
Do you have any repo example of it. I’m a big fan of MVP and I’ve looked at your Droidcon Berlin presentation ( Great talk ), but I can’t imagine how you can separate everything from the activity. For orientation changes or for Intents what do you do? You send all the events to another activity or fragment and let it decide? Thanks
Hey Dragos,
In one of the earlier comments Max asked for code examples and I linked to some.
As for save&restore and configuration changes, you don’t really need to separate anything from Activities and Fragments. Handling of lifecycle is the natural responsibility of controllers. See for example this Fragment in my old app (the code in there is not clean).
And how is this different than giving everything to the presenter?
I’m not sure I understand what you ask. Fragments are controllers/presenters, so handling this kind of stuff is their natural responsibility. It’s UI logic that should be extracted out.
I don’t really like this article much. It makes a lot of assertions based on information that has nothing to do with the topic. Stuff like “This is good, because Netflix made it and they made RxJava” are not really helpful. I feel like this architecture is still miles behind what the web is already pushing with MVI with Cyclejs or Elm.
As far as the architecture is concerned, I still think it misses the whole point of MV?. The point is that your view can be interchangeable. Once you have that you can break down things as you want pretty easily. Telling everyone to write there “View” as a plain old java object only affects the UI layer. Because you have the “View” interface at all, you have isolated you UI concerns from the rest of the app. How you break down the UI from there might as well barely matter. Each app will have different problems, constraints, and goals. Not every app wants to AB test 5 different types of a control.
p.s. I don’t think that we can make a blanket statement that Netflix has some of the best UI skills on Android. The UI complexity they have to deal with IMHO is MUCH smaller then the mast majority of apps on the market. I think it does injustice to some of the good engineering that other companies do to tackle difficult UI problems. Something like Airbnb’s epoxy shows just how much more complicated the UI of other apps can be.
Hello David,
Thanks for your comment.
I respectfully disagree on many points that you raised. However, given how much content about this architecture I already produced, I don’t think I have anything to add in this reply. Let me just say that if you think that the main point of MVx is “interchangeable view”, then this architecture is the best MVx out there by your own definition.
What I do want to clarify is that in no place did I say that either Netflix has “best UI skills” or that other companies don’t “tackle difficult UI problems”. I’m surprised that that’s the impression you’ve got from reading this post.
There is a reason why Google will not stop pushing guidelines. So much of fragmentation in the community over the last few years (not just arch) just creates fatigue and high learning curve for new developers coming into Android. This is not good for Android ecosystem. It is not about what is the right way, companies look for stable way of doing things which reduces pain point when responding to changes, hiring etc. Their bottom line is not tech but the business model and tech is just a means to the end. AirBnB’s ReactNative experience is a classic example, RxJava’s learning curve is another one. Google will focus on majority of devs and not just a few.
Hello Peter,
Let’s assume that Google’s intent is indeed noble and they want to make our life easier. This still doesn’t explain why they knowingly promote an inferior approach which contradicts their own understanding of Android architecture. If developers’ well-being would be the main goal, it would make sense to give them the best tools and practices, right?
In addition, even if their intent is noble, the consequences might still be very bad for developers. There is no shortage of APIs and practices in Android that were introduced by Google to “help developers” and turned out to be complete fiasco (e.g. Loaders).
Therefore, IMHO, we have all the reasons to be skeptical about their current efforts and willing to explore more mature approaches.
Hi Vasiliy,
Nice article. At first I thought this is very logical. Making activities and fragments would solve come problems I had. But what about testability. My presenters are fully testable for now. But not views. I think this approach will reduce coverage. What do you think about this?
Hi Huseyin,
Glad you liked the article.
When I say that Activities and Fragments are controllers/presenters, I don’t mean that you should put all the code inside these classes. Just like other components of MVx, they can (and probably should) be composed of several other classes. Therefore, you can use almost the same approach that you’re using now to unit test your presenters.
For example, take a look at this standalone controller class. I extracted it in one of the lectures of my architecture course to demonstrate how to make the code unit testable. I’m pretty sure it’s very similar to your current presenters.
I’d like to see you post an article about Uber’s RIB architecture. I’ve used almost all the MV* architectures out there even FLUX and Redux in mobile but nothing comes close to the ease of development I’ve seen with RIB.
Hello Andrew,
I haven’t used RIB, therefore I’ll probably won’t write such an article.
However, from the review I did when they announced it, I got an impression that it’s very unfortunate approach. First of all, the idea of representing application’s state as hierarchical structure sounds a bit off. Second, they definitely abuse dependency injection and make things much more complicated than needed.
In addition, if you read this post by Uber engineers, you’ll find this gem:
This paragraph (and the entire discussion of MVC in that blog) is so much off, that I truly suspect that there was no real motivation behind RIB. If you have 3000+ LOC classes, it’s not the architecture.
Lastly, it looks like Uber employs more than 200 Android developers. With all due respect, I can’t see how their apps justify such a massive workforce. With proper engineering practices in place, I’d expect this number to be lower by a factor of 2 at least.
However, these are my absolutely theoretical insinuations and I can be absolutely wrong. Therefore, I’m more than willing to hear about your own experience with RIB.
Hello Vasiliy.
I’ve been using this approach in my personal projects(with MVP) and gladly talking about it to other Android developers. But I’m getting some responses like “MVVM is the new standand”, “you’re showing me MVC code that nobody uses anymore” etc.
I really would like to see a example with MVVM, and what would be in charge of ViewModel and what would be in charge of Activity/Fragment.
Thanks and please keep posting, your texts are among the most important things in Android community