On the never-ending journey to go from hobby programmer to professional, I am always on the lookout for good programming practices. A couple of weeks ago, I found a sample Android TODO app from Google. This app was created to demonstrate how one might organize and architect an Android application. In this post, I'll discuss what I learned from this project.
Android environment
I haven't done any Android programming in a while, so I had to spend some time getting my Android Studio, the SDK and other things up to date. After a few rounds of downloads, updating and restarting, I was ready to work.
I read that that the new version of Android Studio had some big improvements in emulator performance, but I didn't really notice much difference - things are still bad. On both the emulator and on a real phone, I ran the app without any issue. But the emulator performed terribly with the instrumentation tests. First, some of the tests failed only on my emulator. Second, the emulator took about 20 minutes to run all tests, whereas the phone took about 2 minutes.
It looks like I can do some developing with the emulator, but given my set up, it's still not really a viable solution. For now, I'll just move on.
File organization
When you build projects with Android Studio, it creates some folders and files for you. The top level of the todo app looks like this:
app/
build/
build.gradle
gradle/
gradle.properties
gradlew
gradle.bat
local.properties
settings.gradle
todoapp.imp
and that is pretty similar to all Android apps that I've created in Android Studio.
The major difference I see in this sample apps and ones that I have worked on is that there are a lot more src folders:
app/src/androidTest
app/src/androidTestMock
app/src/main
app/src/mock
app/src/prod
app/src/test
The main/
folder holds most of the code that is used in the app. It will be used in all build variants and flavors.
There are two product flavors listed in app/build.gradle
, mock
and prod
, which correspond to two of the src folders. They both have files that define a class called Injection
. This is a little interesting and new for me. The prod and mock versions of this class do the same thing except the mock uses a faked class, which is also defined in the mock directory hierarchy. So, depending on whether we are building a mock or prod version of the app, we will use real or faked classes.
This leaves three test folders androidTest
, androidTestMock
, and test
. Based on the comments (I think): test
defines unit tests; androidTest
defines integration tests; and androidTestMock
defined integration tests that use mock classes. I found this naming to be a little confusing at first, but I think I get it now -- since android is the instrument we're using, androidTest == instrumentTest.
Now that I have a handle on the file organization, I'll look at some code.
Model view presenters
This todo app is implemented using a Model-View-Presenter (MVP) architecture.
In android, things start in an Activity class, and it creates each part of the MVP app. For example:
- TasksActivity is an AppCompatActivity
- TasksActivity creates a TasksFragment which is the View
- TasksActivity creates a TasksPresenter which is the Presenter
- TasksActivity creates a TasksRepository which gives access to Task objects which is the Model
The Presenter is constructed with references to the Model and the View.
mTasksPresenter = new TasksPresenter(
Injection.provideTasksRepository(getApplicationContext()),
tasksFragment);
and the view is aware of the presenter, like so:
public TasksPresenter(
@NonNull TasksRepository tasksRepository,
@NonNull TasksContract.View tasksView) {
...
mTasksView.setPresenter(this);
}
This pattern is done for each of the different Activity's. Data from models are processed by the Presenter to be rendered by the View. Conversely, updates from a user can be sent through the View to the Presenter onto the Model.
Conclusion
This sample app is nicely organized and it's something I can emulate in my projects.
No comments:
Post a Comment