Gradle builds that only load what you need
Gradle projects have a tendency to grow until they become painful to work with. As more modules are added, both configuration time and IDE sync time creep upward. Splitting a codebase into many modules is a common mitigation, but it only works if the build configuration stays disciplined. Otherwise, Gradle ends up configuring projects that have nothing to do with the code you're actively editing, and you wait for it.
Dropbox's Android monorepo is a good example of the problem. It contains almost 600 projects, most of which aren't touched by engineers during a typical day. Yet Android Studio insists on loading them all on every sync. The team wanted a way to tell Gradle which module they're working in and have it ignore everything else.
The manual approaches don't scale
One option is to comment out include("...") statements in settings.gradle.kts for projects you don't need. That works for tiny projects but gets unwieldy as the dependency graph becomes more interconnected.
Another option is to extract all includes into a separate file so you can swap between configurations by applying different files:
//apply(from = File("project-1.settings.gradle.kts")
//apply(from = File("project-2.settings.gradle.kts")
//apply(from = File("project-3.settings.gradle.kts")
apply(from = File("settings-all.gradle.kts"))
But the number of permutations explodes as modules grow, and keeping all those settings files in sync becomes a maintenance burden of its own.
Gradle already knows the dependency tree, though. The obvious question: why not have Gradle generate the trimmed settings file automatically?
Focus: a settings plugin for targeted builds
Dropbox's Focus Gradle Plugin does exactly that. It evaluates the project configuration and produces a unique settings.gradle file containing only the dependencies needed by a specified module. A .focus file at the repository root points Gradle to that generated settings file.
With those files in place, both Gradle and Android Studio configure just the required modules on sync. To revert, delete the .focus file or run the clearFocus task, and the original full build is restored.
For Dropbox's design systems team, focusing on the UI Components Playground sample app cuts IDE sync time from 1 minute to 15 seconds. In other cases, engineers have seen syncs drop from 2 minutes to 20 seconds.
Focusing a module is a single command:
./gradlew :applications:uicomponents_playground:focus
This creates a focus.settings.gradle file in the module's build directory and a .focus file at the project root. Syncing in Android Studio then loads only the required modules. Switching to a different module later is just a matter of running the focus task for that module and syncing again:
./gradlew :dsys:components:focus
To return to the full project, remove the .focus file or run:
./gradlew clearFocus
Setting up Focus
Focus is a settings plugin, so it's applied in settings.gradle(.kts). The plugin is published to Maven Central, which needs to be added as a repository in your pluginsManagement block:
// settings.gradle(.kts)
pluginsManagement {
repositories {
mavenCentral()
gradlePluginPortal()
}
}
plugins {
id("com.dropbox.focus") version "0.4.0"
}
Next, move all include statements into a settings-all.gradle file:
// settings-all.gradle(.kts)
include ':sample:app2'
include ':sample:lib2c'
include ':sample:lib-shared'
// ...
include ':sample:moved'
project(':sample:moved').projectDir = new File("sample/lib-moved")
Configuration is optional:
// settings.gradle(.kts)
focus {
// The name of the settings file
allSettingsFileName = "settings-all.gradle" // Default
// The name of the pointer file that tells Focus which module to focus on
// This should be added to your .gitignore file.
focusFileName = ".focus" // Default
}
Finally, add the Focus file (.focus by default) to your .gitignore.
Once that setup is complete, each subproject gains focus tasks that let you trim the build to what you're actually working on.
Open source and next steps
Dropbox is releasing Focus as open source on GitHub. It's not at a 1.0 release yet, but the team is inviting others to try it and report issues via the issue tracker. Given how much of an Android engineer's day can be spent waiting on Gradle and IDE syncs, trimming that overhead is a meaningful win.



