 Hello, hello everyone. So my name's Anupoko, and this is the talk I'm doing. You were expecting a different talk. It says so in your brochure, but that guy couldn't make it, so I'm the unpaid substitute teacher. So yeah, we're going to talk about how to write whatever that's. So MVP on Android and how you can use that to make your apps slightly better. I'm a GDE, which means I'm very smart. And I work for a startup called Clear Tax. So we do tax stuff, which is, well, we make it easy for you to pay tax, or as easy as it can be within the Indian government. And we're hiring. My boss told me to set that, so we're hiring, looking for backend developers, sales people, anybody who brings in money. OK, cool. So let's get started. So OK, so first of all, MVP is not minimum viable product. It's model view presenter. It's an architectural pattern you can use in your code. And so why do we use this? Is the first question? Yeah, so MVP allows you to get a clear picture. This is what most apps look like right now. There's data. There's views. And everything is just jumbled. And everything is happening everywhere. MVP will make your apps look like this. So it has three components, the model, the view, and the presenter. So model is your data. Anything, it can be like a database. It can be a server, all that stuff, API, whatever. Views are basically your Android views, activities, fragments, anything that has to do with the UI thread, runs on the UI thread is a view. Presenter is a class that coordinates between these two. We'll see how. The second thing is separation of concerns. It helps your code be decoupled. And decoupled code is better code because it is easier to modify. It's flexible. Each layer will do its own stuff. And if you want to change any layer at any point of time, you can do so without affecting the other parts of your app. Oh, yeah. And this is not really directly related to MVP. But if you combine it with RxChile and a bunch of stuff, you can do this. So basically, most of the problems that we have in Android and asynchronous things is that we have a lifecycle to worry about. So if you do all this stuff outside of the lifecycle in your model, then you don't have to worry about life cycles. This is the main thing. You can test stuff. So testing is the whole reason we do architectures in the first place. So you can get confidence in your code. When you ship a new feature, change something existing, so yeah. And OK, so this is what it looks like. So we have the model, the view, and the presenter. Notice the little arrows. So the presenter is the one coordinating between the model and the view. And user input is always on the view. And the view talks to the presenter. The presenter goes to the model, gets the data, whatever. Updates it back on the view. The view never talks to the model directly. OK, so this is how it looks on Android. All your activities, fragments, and widgets, everything the framework provides that has to run on the UI thread are views. Data layer is basically models, SQLite, API, content provider, anything that has nothing to do with Android really is your model. Yeah, so that's just what I said again. So any user input has to always be on the view. This differs from other architectural patterns where, for example, in MVC, the user inputs are handled by the controller. Here, it's always handled by the view. So one thing you have to remember is you have to keep your presenters and your models Android free. Otherwise, this whole pattern doesn't work. So the main thing we're trying to achieve in this architectural pattern is to isolate these layers. So make your presenters and your models non-Android so you can test them on the JVM without needing a device or anything. Everything that happens on the UI thread is done by the view. I keep saying this again and again, but I just want you to really know it. Keep it simple. Too much architecture is bad. DI makes things easier. We saw talk about Dagger 2. That's a good one. Or you can just roll your own little DI framework on the fly. We use mocking frameworks to test it. You'll see how the tests are done. So use things like Mockito and Power Mockito. And there's other Mockitos. OK, so that's enough talk. Everything I'm about to show you is on GitHub, so you can check it out later. And over to Android's 2.0, where I have made the font size really, really big. So you can see. So let me show you the sample app. This is the sample app. It only does two things. So there's the main activity and there's a post activity. So the main activity has one button. You click it, it opens this screen, and it gets some random gibberish from a server. That's all it does. So that's the app. And we're going to see how this simple app is constructed using MVP. And we're going to see how we can test it. So as with all Android things, let's start with the main activity. So you can see the main activity. So let's look at the structure first. Maybe that'll help. OK, so there's the main activity. And in our case, this is a view. So it implements a contract called the main screen. So the presenter is not supposed to be aware that this is an Android thing, that we're talking to activities. It's just supposed to talk to this abstract concept of a screen. Now, traditionally how MVP was used, you could write the same code for your desktop app and your another app. Just change the UI bit depending on the platform. And if you're using something like Java which runs on multiple platforms, they'll be very easy. So let's look at what this thing does. So main screen is a contract. And the contract only has one method in it. It says launch post activity. That's the only method which we have to implement. Cool. So the main presenter implements that method. All it does is fire an intent to start the next activity. Simple so far. So now we have a click listener for the post button. And this click listener just delegates the click to the presenter, which we are initializing here using dependency injection through dagger. You don't have to do that. It's just something I do. So basically what happened so far is somebody clicks the button, the user clicks the button, the click listener is called. And then the click is delegated to the show post button click method in the presenter. Now we can look at what the presenter is doing with this click. OK, there. So this is just the presenter constructor. And this is the button. OK, so what it's doing is calling the main screen again. So you can see the main screen is being passed here. Now you can see that it's not an activity. It's just some abstract concept called a screen. And it's going to call this method, which we implemented through the interface, back onto the main screen, which will launch the activity, the second activity. So you might be wondering why all this jumping around. So let me summarize quickly what happened. So the user event was passed to the main activity, which was the button click. The button click was passed to the presenter. The presenter processed it. In this case, it didn't really need to do anything with it. So it just passed the event back onto the main activity. And the main activity launched the next activity. So the reason we do this is so we can unit test this. So let me show you how that looks. So there's this annoying build variant thing that you have to do every time in Android Studio when you want to switch between unit and other tests. So this is the test for the presenter. So this presenter only does one thing. Take the user input and call the other method, the launch, the next activity method on the main screen. So what is actually happening once you call that method is defined in the main activity, so the presenter does not have to worry about that part. So all we need to test here is on the given input, when we call that method, does the other method on the main screen get called or not? So that's what we're doing here. We make a new presenter, really, really long test names, standard feature of Java. Test should show toast and launch activity on show post button click. This should not say show toast. It was in an earlier implementation which I removed. So let's just say test should launch activity on show post button click. So this is the interesting part. So we're not talking about activities here anymore. In this test, we're just initializing a main screen, which is just an interface that the main activity implements, and we're mocking it using Moquito, which means this actually doesn't do anything. It's just a mock implementation. Now, we call the method on the main presenter that we would call in the main activity when the user clicks that button, which we do here. Then we verify that on the main screen, the corresponding method to launch the next activity is called. So we tested the presenter part. The presenter is doing what it's supposed to do in this test. Now, there is no model here, so we don't need to test that, but we will see that in the next part. Now, that's one part that you tested. Now, you want to know that the main activity also does its part, so we go and check that. So this is the test for the main activity, which is a Espresso UI test. Now, these tests will require an Android device or an emulator to run on. The other test does not. It's a JVM test, because as you can see, there was no Android in here at all. No Android anywhere. So this is the advantage it gives us. You can test your models and your presenters on the JVM using standard unit tests, and you only need to test your main UI code on your main thread, which is on a device. So let's look at that test. We're just creating a main activity here, and at this point, we are actually talking about real activities, because that's what we want to test. Then, again, yeah. So test should launch post activity when show post button is clicked. How we're doing that is that's unusual technical issues and we're back. So yeah, so the test. So we're going to click the button using Espresso. Then we're going to, on the next activity, there's a recycler view. We want to see if it's displayed. So that means the main activity has done its job. So this way, we tested the presenter and we tested the activity in isolation. So you can actually run these tests, which I hope will pass, but the internet is a little flaky. This is what you get for buying a MacBook Air instead of a MacBook Pro. Yeah, the posts aren't loading really because of the internet, but it's fine. We'll assume it passed. So yeah, so that's how you test your main activity thing. So now we can look at the second one, which is the post activity. This is a little more complicated because we are going to have a model in this as well. Okay, so this is the post activity. So we have a presenter for this as well. You have to remember that every view will have a corresponding presenter. And when I say view, I mean like activity or fragment, not for every single text view and stuff like that. Right, okay. So we have an adapter. We're gonna just, yeah, okay. So there's the post presenter and we're calling this method on it called load post from API, right? So the view in this case or activity is not actually doing the loading of the data from the model. It's just delegating it to the presenter. Now the presenter is gonna go do it for us there. Okay, now the presenter is calling the API, which is the model in this case. It could be a database. It could be shared preferences. It could be anything. So it's gonna, it's using RxJava. So it's gonna get observable, subscribe, all that stuff. And it's just gonna get the data from the server, right? So we can actually look at this API, right? So that's the API. And it's just, there's this website or jsonplaceholder.something-type-icode.com which gives you like random paragraphs which you can use in your demo apps too. So yeah, so we get the API and we subscribe to it. And we get the data, which is a bunch of new posts. And in this case, we're not making the post activity implement an interface and call a method on it. We're just gonna use an event pass and post this thing, this whatever new post we've got onto the event pass. And we're gonna get subscribed to it in the activity and get it back. The reason is that it's just two approaches to doing this. You can either make them implement an interface, like some kind of screen interface and call method directly on them. Or if you want, you can use an event bus in between to communicate with these to make it even more decouple, right? You can do the same with your model and your presenter as well. But just don't go catching your model events in your views because that would be not MVP, okay? So we have two cases here. We have the new post coming in or we have an error condition and then we throw an error event or a new post event, right? Cool, so let's go to the post activity. It does implement an interface, but it doesn't really do anything. No methods in there. That's just there, but we don't need that. Cool, so we load post from the API and as you can see, we're subscribing to the event bus here and unregistering and on start, on stop. We're gonna initialize a recycler view with stuff and we're gonna catch the events here. So when we get new posts, we're going to add them to the adapter. Now, this is business logic, sort of, when you're adding stuff and removing stuff from your adapter and stuff like that, but it's still Android stuff. A concept of an adapter, a view, a recycler view all exist in Android so your presenter should not know about them. So all your business rules, anything that has to do with your app logic, which is not Android, should reside in your presenters. Well, it should reside actually in your model and your presenter should just get the data and marshal it, transform it to whatever form your view needs and then you can fire an event or call a method on it. Okay, so when we get new posts, we're gonna add them to this adapter that we have for the recycler view and if we get an error, the presenter is gonna call this method which is a show error method and then we have a hide error method to correspond to it as well. Okay, so now we can see how we can test this. So once again, we're gonna test the presenter first on the JVM, no Android necessary. So what does the presenter do? The presenter doesn't actually load the data, it just schedules a data load on the API and the API, which is our model in this case, is actually doing the loading from the API, from the server. So what we have to test is if the presenter is successfully scheduling the load, right? And then we can test the API to see if the API is doing its job. In this case, the API is just a call to retrofit the library, I'm sure everybody here knows. So retrofit is tested by square, obviously, so we don't need to write tests for that. So, okay, so we have an observable, which is our observable, which is just a mock observable. It's not actually going to return any data, it's only going to return the data, we tell it to return. Then we're gonna define the return values, which is this whole chain of calls that you see here. Basically, we're mocking this whole chain of calls that you see here. Get post observable, subscribe on, observe on, all that stuff. Because we want it all to return our mock observable instead of the modified one that actually tries to load data, right? So we do all that here, and then here, and then here. And then we call the method that we wanna test on the presenter, okay, load post from API. Now we wanna check whether all these methods were called intern. So, okay, did we get the observable? Yes, did we subscribe on NiO thread? Yes, did we observe on the main thread? And then did we subscribe eventually on a subscriber which takes these events, right? So that's all the presenter is doing. And we've tested that in this unit test. Now we can check out the actual UI test. Okay, so this is the post activity actual test. So, we're gonna test if it shows the new post when it actually gets the, so the responsibility of this class, this activity is not to load the API, data from the API, or do anything else. It's only job is to, once it receives the post, show it. And then if it receives an error, show in error condition, right? So we've isolated it, the logic that we want into all these separate layers so we can test them independently, right? So we're gonna make up a bunch of fake posts here. And we're just gonna fire that event on the event bus. So you see the reasoning behind how we can test this here. So what the presenter was doing, once it got the data, was firing an event on the event bus and then the main activity to receive it, a post activity would receive it and do something with it. We're just shortcutting that process and directly posting an event on the event bus with these posts so the post activity would have to receive it and then do what it's supposed to do. Okay, so once we post this event, which is posted on the UI thread, so it's going to be synchronous. It's going to go process it, show the recycler view, all that. We check if the recycler view is visible and we check if the error view is not visible. Then the next test is show an error view on network error. So what happens on network error? We post an error event from the presenter, right? So we're just going to post that error event directly here and we're gonna check if the error view is visible and the recycler view is not visible. So we're basically testing the whole whatever, all the layers in isolation. Now there are two types of UI tests, broadly speaking. One is a instrumented unit test and one is a functional test. So in instrumented, you can do both with MAP. So in instrumented unit test, you basically wanna do an unit test on activity or something. It's going to mock the API, it's going to mock the database, it's going to mock everything else. It just wants to test its own functionality, right? But you need a context object and you need some Android UI stuff to actually see this happen. So that's basically a unit test, but it's instrumented, it runs on an actual device. Now then there's a functional test which is actually testing the whole, you call the actual API, you call the database, you make the user login or whatever you have to do on a real thing. It could be a production server or like a mock server, yeah, a dev server or something, but you are actually making all these calls. So what we're doing here is this is basically an instrumented unit test, right? You want to unit test the activity and so we're mocking out all the other layers. And let's see if this will run on my MacBook Air. Okay, seems to run, but again, the network. So that's basically the talk. I hope you kind of got a high level over how MVP works and what it's useful for and why we do it in the first place. So it might look like it's a bit more effort writing code the first time, like I have to do all this now, think about which layer to put my code in and how to communicate between the layers. But in the long run, it really pays off because you can test your code and you can change features and you can add new features and you can have like a solid architecture in your app which new developers coming onto your team can quickly adapt to. And yeah, testing is basically the thing. So you have less bugs and happier users, okay? So questions. How MVP is better than MVVM? I think on Android at least MVVM is harder to test because the view model is not something you can mock. It's based out of XML and it's actually tied to your actual models. I think you can figure out a way to mock the models that it depends on, I suppose. But I think this is just an easier way to do it and data-winning library is quite new and haven't really experimented enough with it to have an informed opinion at this point. You know, I hear lots of news about, I mean, lots of noise about MVP, MVVM. If that is really, really great, then why Google is not using it? And even if you look at the AOSP code as well, like, you know, as you mentioned, testing is quite easier in this one. So if that is the case, then Google might have written something, but still if you look even the testing code to test some features, some functionality, some component, it still works. Well, Google is using it. If you look at the code lab, they published at the Android Dev Summit this year. It's all based on MVP. So it's not like they're recommending it, but it's like, okay, here's one architecture you can use. So they are using it. As for the internal labs, I don't know what they're doing. Is it a, shouldn't the logic of creating intents be also in presenters? Because many a times when you... Hang on, I can't see you. Yeah. So many a, because, isn't it a good idea to, to push the logic of creating intents even in the presenters because many a times you even pass data in presenters and there's logic associated with that as well. And you definitely want to unit test that as well. And since now you can even mock Android, Android stuff with the new Android jar. I guess that can be also done, but then intent require, in most cases it requires a context. You can mock the context. So then you have to mock the context, but I suppose that can be done also. And... So this is the kind of stuff I meant when I said the KISS principle applies, like do either one, because you know, this is not the stuff you should be really worrying. If you have like a high level architecture that allows you to test your apps, effectively it doesn't matter. And in functional tests, you mentioned that it's, that you should use a debug server to test the, to test the entire functionality. Is it, is it using that or using something like retrofit mock a better idea because then you don't need the server to run that test and it's really fast. Or do you recommend using a debug server surely? I guess so, but I, in my experience, like using any mock server is still not a real thing because it's still deterministic, whereas a real server can fail on you in many ways that you just don't expect. Okay, but if the things like OK HTTP and retrofit allow you to test delays and fails. So if that works for you, that's fine. Okay, and this is with specific... You guys use something like a, you guys inject transformers in, so that all RxJava stuff can run on the UI third while you're testing or don't, you don't, do you not do that? No, not at the moment. So what we, what I do personally is I take the RxJava stuff and put it into the presenter. And yeah, and then it communicates why an event bus or something like that. So I can just pass in the, just throw the, you know, push the events onto the event bus and then I don't have to worry about it because I know that this event will be called once the subscriber completes. So I can just test it like that. But will that not be like right when you're doing the functional test because... That's true. So there is a Espresso idling resource for RxJava by the folks at Novoda. It is quite cool. I kind of adapted it to my own needs a little bit, but it's still not like, you know, anywhere in your production that I can... And is it a good idea to use event bus because then you have to run instrumentation test to run everything? Because if you push that to the presenter and then the test can completely be JVM based because then it's, because you're mocking the presenter, but event bus has to be run in an instrumentation. You don't have to use an event bus. Like I'm just asking a recommendation. These kind of questions, like they actually really depend on your specific app. So I don't know. Like my general thing is if you have a few events, it's fine, but, you know, your mileage may vary. Do you guys use the, an RxJava implementation? Yeah, I've used that as well. The only thing with that is you don't, you, yeah, it's pretty much the same. So it's not. Cool, awesome. So in your post activity, right? You come back from Rx to the activity through an event bus. Wouldn't it, to follow up your MVP kind of thing, wouldn't it make sense you come back to the presenter and then the presenter sends that data to it? That's what, that's what's happening. I believe you came back directly to the activity. You're on. So the event is, Event bus posted to the activity, right? Yeah. Should have posted to the presenter. Well, the subscriber is in the presenter. So the data comes into the presenter and then the presenter uses the event bus to pass it on to the activity. Okay. So in that case, how do you handle threads? So let's say I had to do this across different, a multi-project setup across different modules. So yeah. So my solution to that for now is I don't handle threads. So that's why my testing is just, okay, post this event. I know this event will be posted when the, you know, when the network stuff happens and I come back to it. So I just test the effects of that event. Now, if you're using, I think Wally or the standard Android, HTTP URL connection has espresso idling resources that will wait for this. Rx, as I mentioned, no other guys have espresso idling resource implementation for Rx. I don't know how good that is because I haven't tested it, but I expect something soon to pop out of the Rx world to deal with this. One last thing is how do you test if you at all do filtering, mapping and use Rx to its full potential? How do you test those? Just test the effects. Transformations. So as long as you get the effect, I think that's what your users care about. So here. So which architecture would you use if you want to abstract your model? So just in case you'd have something in the memory, something in the database and something on the cloud. So how would you abstract that? So my go-to way to do like models is to have something called a manager class, which I use. So for example, if you have posts in this case, I would have a posts manager class which would actually call the API, get the data and then cache it in your database. And then the next time somebody asks for the same data, you first check in your database if you have it. If you have it, then you just post an event saying that I have it, here's the stuff. If not, then you make an API call and cache it for the next time. And these manager objects have to live outside of the life cycle so they can be singletons. As long as you don't have like a million manager objects, it shouldn't affect your memory too much. And the manager object should be lightweight in the sense that they shouldn't hold too much data in memory, they should be constantly writing it to the desktop. So just in case you want to cache it in memory and let's say the user comes at the same place and you want to have the same effect from the memory rather than fetching it from the database. What's the preferred approach? I didn't. We want to cache some data in memory so that we don't get it from the, I mean, if the data is called. So you can use the LRU cache that. Just the LRU cache will work. Anybody else? Any other questions? We still have some time.