If you have ever encountered an error Cannot fit requested classes in a single dex file when building an Android application, then you are already familiar with the problem that it solves MultiDexApplication. This is not just a technical term, but a key mechanism that allows you to bypass the platform's limitation on the number of methods in one Dalvik by the number of methods in one .dexfile. Without it, many modern applications simply could not work.
In this article we will look at what it is MultiDexApplicationwhy it appears in Android projects, how to integrate it correctly and what pitfalls may arise. You will learn when you really need to use multiple .dexfiles, and when the problem can be solved by optimizing the code. We will also look at alternative approaches that can save you from having to work with multidex at all.
The material will be useful both for novice developers who first saw an error about exceeding the limit of methods, and for experienced specialists who want to optimize the assembly of their application. We will not limit ourselves to theory - in the article you will find practical instructions, code examples and solutions to typical problems.
What is MultiDexApplication and why do you need it
MultiDexApplication is a class that is the successor of the standard android.app.Application, which allows an Android application to use multiple .dexfiles instead of one. But why is this necessary at all?
The point is the limitation of the virtual machine Dalvik (and partially ART), which historically supported no more than 65,536 methods in one .dexfile. This limitation is due to the file format .dexwhere methods are indexed by 16-bit values. When your application (along with all libraries) exceeds this limit, the build fails.
With the advent of Android 5.0 Lollipop (API 21) native support for multiple .dexfiles was introduced, but for older versions of Android additional configuration is required. Here MultiDexApplicationcomes to the rescue, which:
- ๐น Loads additional
.dexfiles when the application is launched - ๐น Ensures compatibility with devices on Android 4.4 (API 20) and below
- ๐น Simplifies the build process for projects with a large number of dependencies
It is important to understand that MultiDexApplication is not a panacea, but rather a โcrutchโ to bypass the limitation. It increases the cold start time of the application and can lead to performance problems, especially on older devices.
How the limitation on 65,536 methods works
To understand why there is a need for MultiDexApplicationyou need to understand the nature of the limitation. Each .dexfile in Android contains:
- ๐ List of classes and their methods
- ๐ข 16-bit indexes for links to methods
- ๐ Link table between classes
A 16-bit index allows you to address a maximum of 65,536 unique methods (216 = 65,536). When your application, together with all libraries (Firebase, Retrofit, Room and others) exceeds this limit, the compiler cannot pack everything into one file and throws an error.
Interestingly, this number includes not only your methods, but also:
- ๐งฉ Methods from all connected libraries (including transitive dependencies)
- ๐ Methods generated by the compiler (for example, for Kotlin or Data Binding)
- ๐ฆ Methods from Android SDKif they are connected via
compileOnly
Modern applications easily exceed this limit. For example, a project with Firebase, Dagger 2 i RxJava can contain 40-50 thousand methods only from libraries, not counting your own code.
Use the tool ./gradlew :app:analyzeDependenciesto see the full list of dependencies and their size in methods.
When you really need it MultiDexApplication
Exceeding the limit of methods does not always mean that you need to immediately switch to multidex. Here are cases when MultiDexApplication is really necessary:
| Scenario | Is it necessary to use MultiDex | Alternative solution |
|---|---|---|
| Application for Android 4.4 and below | โ Yes | Refuse support for older versions |
| Project with 70,000+ methods | โ Yes | Dependency optimization (see below) |
| Use Instant Run in Android Studio | โ Yes | Disable Instant Run or update Gradle Plugin |
| App only for Android 5.0+ with 66,000 methods | โ No | Include multiDexEnabled true without inheriting from MultiDexApplication |
If your application is focused only on Android 5.0 (API 21) and above, you you can do without MultiDexApplicationby simply enabling support for multiple .dexfiles in build.gradle. However, for older versions of Android, you cannot do without inheriting from MultiDexApplication .
Also remember that using multidex:
- ๐ข Increases cold start time (sometimes by 500+ ms)
- ๐ฆ Increases APK size (additional
.dexfiles) - ๐ May cause problems with Instant Run v Android Studio
If your application only works on Android 5.0+, try first optimize dependencies before moving to multidex.
How to set up MultiDexApplication in a project
Integration MultiDexApplication consists of several steps. Here are step-by-step guide:
-
Add a dependency to
build.gradle(module level):implementation 'androidx.multidex:multidex:2.0.1' -
Enable multidex support in
defaultConfig:android {defaultConfig {
multiDexEnabled true
}
} -
Create a descendant class (or change an existing one
Application):public class MyApplication extends MultiDexApplication {@Override
public void onCreate() {
super.onCreate();
// Your initialization code
}
} -
Indicate your class in
AndroidManifest.xml:<applicationandroid:name=".MyApplication"
...>
For projects on Kotlin the code will look like this:
class MyApp : MultiDexApplication() {override fun onCreate() {
super.onCreate()
// Initialization
}
}
If you use ProGuard or R8, make sure that the obfuscation rules do not remove critical classes from additional .dexfiles. Add to proguard-rules.pro:
-keep class com.android.support.multidex.** { *; }
โ๏ธ Checking the MultiDexApplication setting
Project optimization: how to avoid MultiDexApplication
Before Instead of switching to multidex, try optimizing the project. Here are some effective ways to reduce the number of methods:
- ๐งน Remove unnecessary dependencies. Use
./gradlew :app:dependenciesto find and remove unused libraries. - ๐ Replace heavy libraries. For example, instead Guava use lighter alternatives.
- ๐ฆ Use
compileOnlyfor libraries needed only at the compilation stage. - ๐ ๏ธ Include minifyEnabled and shrinkResources to remove unused code.
An example of dependency optimization in build.gradle:
dependencies {// Instead of the full version of Firebase
implementation 'com.google.firebase:firebase-analytics-ktx'
// We use only the necessary modules
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.2'
implementation 'androidx.lifecycle:lifecycle-livedata-ktx:2.6.2'
// compileOnly for annotations
compileOnly 'org.jetbrains:annotations:24.0.1'
}
Another effective way is to use Dynamic Feature Moduleswhich allows you to separate parts of the application into separate .apkfiles that are loaded on demand. This not only reduces the size of the main .dexfile, but also optimizes the loading of the application.
Which libraries most often โinflateโ the number of methods?
According to the analysis of popular projects, the most methods are added: Firebase (especially if you include all package), Play Services, Retrofit with many converters, RxJava/Coroutines with a full set of operators, as well as libraries for working with graphics (Glide, Picasso, Coil).
Typical problems with MultiDexApplication and their solutions
Even after correct configuration MultiDexApplication you may encounter problems. Here are the most common ones and ways to solve them:
โ ๏ธ Attention: If you use Instant Run v Android Studio, multidex may be unstable. It is recommended to either disable Instant Runor use Apply Changes instead Apply Code Changes.
1. Error "No implementation found for ... "
This error occurs when a class from the main .dexfile tries to access a class from an additional .dexfile that has not yet been loaded. Solution:
- ๐ง Make sure that all critical classes (activities, services, providers) fall into the main
.dexfile. - ๐ Create a file
multidex-config.proormultidex-config.txtin directoryapp/and indicate in it the classes that should be in the main.dexfile.
2. Increasing startup time
Loading multiple .dexfiles increases the cold start time. To reduce this time:
- โก Use
MultiDex.install(this)inattachBaseContext()instead ofonCreate(). - ๐ Optimize the main
.dexfile, leaving only the most necessary classes in it.
Example of optimized code:
public class MyApp extends MultiDexApplication {@Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(base);
MultiDex.install(this);
}
}
3. Problems with ProGuard/R8
If after enabling obfuscation the application stops working, check:
- ๐ Rules
proguard-rules.profor conflicts with multidex. - ๐ Build logs for warnings about deleted classes.
Add to proguard-rules.pro:
-keep class com.android.support.multidex.** { *; }
-keep public class * extends android.support.multidex.MultiDexApplication
โ ๏ธ Attention: Work details ProGuard and R8 may change in new versions Android Gradle Plugin. Always check the latest settings in the official documentation.
Alternatives to MultiDexApplication
If you don't want to use MultiDexApplication, consider alternative approaches:
- ๐ฆ Dynamic Feature Modules โallow you to break the application into modules that are loaded on demand. Supported with Android 5.0 (API 21).
- ๐ App Bundles โa new publication format that automatically optimizes code delivery to users.
- ๐งฉ Micro-services โmoving some of the functionality into separate services or libraries.
- ๐๏ธ Removing legacy code โcleaning the project of unused classes and libraries.
Configuration example Dynamic Feature Module in build.gradle:
android {dynamicFeatures = [':dynamic_feature']
}
dependencies {
implementation project(':dynamic_feature')
}
App Bundles is a modern approach that not only solves the problem with the limit of methods, but also optimizes the size of the APK downloaded by the user. Google Play automatically generates optimized APKs for different devices.
To switch to App Bundles, change in build.gradle:
android {bundle {
language {
enableSplit = true
}
density {
enableSplit = true
}
abi {
enableSplit = true
}
}
}
FAQ: Frequently asked questions about MultiDexApplication
Is it possible to use MultiDexApplication in a library (AAR)?
No, MultiDexApplication intended only for the main APK application. If your library exceeds the limit of methods, you need to optimize its dependencies or split it into several modules. Libraries cannot contain multiple .dexfiles - this is only supported at the final APK level.
How can I learn how many methods are in my project?
You can use a plugin Android ClassCount or command:
./gradlew :app:analyzeDependencies
The command is also useful to count methods:
./gradlew :app:countDebugMethods
These tools will show the exact number of methods and help identify the most "heavy" dependencies.
Does MultiDexApplication affect performance?
Yes, using several .dexfiles increases the application's cold start time, especially on devices with Android 4.4 and below. On Android 5.0+ the impact is less noticeable due to native multidex support. To minimize impact:
- Optimize the main
.dexfile, leaving only critical classes in it. - Use
MultiDex.install(this)inattachBaseContext(). - Consider switching to App Bundles or Dynamic Features.
Is it possible to disable multidex for a debug build?
Yes, you can enable multidex only for a release build by adding to build.gradle:
android {buildTypes {
debug {
multiDexEnabled false
}
release {
multiDexEnabled true
}
}
}
This will speed up building and running the application during development, but remember that a debug build may not work if the number of methods exceeds limit.
What to do if, after adding MultiDexApplication, the application crashes at startup?
The most common causes of crashes:
- Incorrect configuration
AndroidManifest.xml(class not specifiedApplication). - Conflict with ProGuard/R8 (critical class removed).
- Problems with initializing libraries in additional
.dexfiles.
Check the logs Logcat on subject ClassNotFoundException or NoClassDefFoundError. It often helps to explicitly indicate the classes that should be in the main .dexfile, via multidex-config.pro.