This sample app loads and displays blog posts in a list. By clicking a blog post, you are taken to a detail UI, which shows the entire blog post body and comments.
The app uses a fake blogpost API to load the posts and comments. All data is cached locally, so no unneeded network requests are being made until the cache becomes invalid.
The application has almost 90% test coverage, so adding / changing features is not scary at all. You can always run the tests after making changes, and if they pass, you can be pretty sure you didn't break anything vital.
Actually, there's only about 10 test functions, and the longest one only has 8 lines of code. That's not so much, is it?
By following Model-View-Presenter, Clean Architecture and SOLID Principles, this app becomes:
- Easy to test. Business rules can be easily tested without Android emulators / devices in milliseconds. And the UI tests are't that horrible to write either.
- Easy to maintain. Adding / modifying functionality is easy, and doesn't cause a regression bug hell as everything is separated and tested.
- Independent of external third-party libraries. Cache can easily be replaced with Realm, without modifying the main application logic. The application simply doesn't care about what frameworks we're using.
- Independent of UI. The UI can easily be changed without changing the existing business logic. This could be easily converted to a desktop or even a command line app.
Everything is nicely decoupled. The application isn't dependent on concrete implementation details. They are more like plugins, and they actually depend on the application; not the other way around.
The project has two build variants:
- mock
- Instead of loading real data, populates the blog list and comments from a static FakeBlogApi to make testing easy. Also contains all the tests.
- prod
- The "real" app that actually loads real blog and comment data from a real API. Does not contain tests, they are in the mock variant.
Blog API and Cache implementations. The Blog API is defined in a simple interface that has getPosts()
and getComments(int postId)
methods. The implementation is then automatically generated by the Retrofit library.
Contains the business rules (usecases) that are our applications main functionality. No Android or external dependencies here, just plain Java.
Also contains the BlogPost and Comment models and the PostCache and CommentCache interfaces that the data layer implements for SharedPrefCache.
All the Android-related UI stuff, such as Activities
and RecyclerAdapters
. Also just plain Java Presenter
objects and View
interfaces implemented by the Activities
.