Please choose code language:
Multiple application modules in one Android project
This topic is assigned to JustAlex
hasanraza 2019 October 18 11:29

While Android Studio, Gradle and Kotlin are getting better and better with every release, the real performance bottleneck in modern android development is kapt — kotlin's compiler plugin responsible for annotations processing (you don't write in Java anymore do you?). The chances are pretty high that you use Dagger or other annotation processors to generate code.

Also See: What Is Android System WebView App?

Developers switch git branches dozens of times per day. The code is different in different branches, and the problem is that kapt does not really know what the consequences of these differences are. So, unfortunately, even though a developer works on at most 10% of the whole app functionality, it's quite common to do a clean/rebuild of 100% of the project after every branch change.

Splitting by feature

As the app gets bigger, it’s becoming more and more important to break it into separate modules so that we can enjoy the delights of parallel compilation.

How exactly we are supposed to break the app into modules depends, of course, on navigation flows. In the perfect-case scenario the app flow looks something like this:

Navigation flows in a perfect world

Everything is usually more complicated in practice:

More realistic example of navigation flows

But nevertheless we always have functional parts naturally separated from the others. Different features/flows normally start from different tabs. If you have a login screen, it’s always a good idea to extract it as it’s needed by everyone.

Application feature modules

We can go further and create multiple application modules in one project, so that:

  • every application module represents a simplified version of the app, with nothing else but only one certain feature included;
  • each team/developer only compiles the code they’re currently working on. Even if other feature modules have been changed, they're simply not in your compilation pipeline;
  • the teams are encouraged to work only on the feature they're assigned to. The modules can even be placed in different repositories with different access rights, so you can be sure that a junior developer from another team will not accidentally add a few bugs into your module while you're on your vacations.

For a simple app with a login screen and two relatively independent features like the one mentioned above, the structure of modules would be the following:

The Main App module should be used only by continuous integration software in order to build, test and deploy the final apk and, very rarely, when we need to test cross-feature flows.

The Feature 1 App and Feature 2 App rectangles are green because they're created only for developers' convenience and whatever we do there has no influence on the production main app.

So how do I navigate between features?

As you might have noticed, in the realistic example mentioned above the user still navigates from Screen A to F and from E to C. However, the feature modules (feature1 and feature2) can't depend on each other, so their dependencies should be encapsulated.

There can be other horizontal dependencies between these two modules, like common data models or utility classes/functions. Consider putting them in lower-level base modules. Don't follow the temptation to put everything there just in case though: you don't want to have another huge coupled module. Navigation is the only thing that really needs to be encapsulated.

Let's get into the details module by module.

Login Module

Login Module (login)

Login module login does not depend on anything (only low level base modules probably), and defines an interface LoginNavigation. I know everything about login sequence, but I don’t know where to go after — this is what this module is about.

Feature Modules (with Feature 1 as an example)

Feature 1 Module (feature1)

Feature module feature1 also does not depend on anything, contains all logic required for screens A, B and C, and defines an interface Feature1Navigation which is responsible for all external navigation. This interface has some human readable methods like goToF(), but no specific activity/fragment name is known at the moment here.

This is the module where a developer or a team responsible for feature 1 is going to work on everyday, enjoying its short compilation time because they don’t need to compile ten other features.

Feature App Modules (with Feature 1 as an example)

Feature 1 App Module (feature1app)

Feature 1 App module, feature1app, depends on login and feature1. It defines its own implementation of LoginNavigation that leads user directly to screen A. It also defines its simple "go there don’t know where" StubFeature1Navigation, but we do not care too much because it should not be used too often (or reconsider module boundaries otherwise).

Feature 1 App is going to be compiled and launched every day. However, the code will almost never change here, because it's just an executable container for feature1.

Main App module

Main App Module (app)

Main App Module, app, depends on all other modules feature1feature2login, and is the only module that should know what the real dependencies are. Apart from that, it should not do much though. It’s just a container that defines the main screen of the app and the dependencies between all navigation flows. I don’t care what exactly login flow consists of, but in the end it should navigate to MainScreen. I don’t care how many screens Feature 1 has or what internal Feature 1 flow is, but I know that when it wants to goToF(), it should navigate to Screen F from Feature 2.

The whole structure of modules with injected dependencies will look like this:

Modules and theirs dependencies

Links

As a demonstration of the suggested approach, I created a simple project and published it on Github:

https://github.com/yankeppey/MultipleAppModules

The project uses Dagger 2 as a dependency injection framework which is, it would be fair to say, almost an industry standard nowadays. However, the suggested approach is framework-agnostic and would be valid with any dependency injection framework or implementation.

( Content Source: https://medium.com/mindorks/multiple-application-modules-in-one-android-project-36e86ceb8a9 )

Nadia1 2019 October 26 12:22

Nice to meet you, though we did not know before, but i think i pick interest on you. It will be a pleasure to have mutual conversation with you on gmail, hope you will not get me wrong ? write me back on my gmail address to know what i want to conversate with you.   

aidasami6@gmail.com

You must login to post messages. Click here to log in.