Android Componentization: Architecture, Implementation, and Best Practices
This article explains why large Android projects need componentization, describes the concepts of modularization and componentization, presents a detailed component architecture, and provides step‑by‑step solutions for independent debugging, routing, inter‑component communication, fragment retrieval, application lifecycle distribution, and migration of legacy projects, complete with Gradle and ARouter code examples.
1. Background
As a project grows, compilation becomes slow, merge conflicts increase, and responsibilities become unclear, indicating the need for componentization.
2. Understanding Componentization
2.1 Modularization
In Android Studio, a module corresponds to a logical feature; splitting the app into multiple modules reduces coupling but still leaves high inter‑module dependencies such as page navigation, data passing, and method calls.
Componentization solves these high‑coupling problems by turning each business module into an independent business component .
2.2 Componentization Advantages & Architecture
Benefits include faster compilation, improved collaboration, and reusable functionality. The architecture consists of a shell project , common component , basic component , business base component , and business component . The shell integrates all components, while business components have no direct dependencies on each other.
3. Independent Debugging of Components
Two schemes are provided:
Single‑project scheme : All modules reside in one Gradle project; switch a component between com.android.application and com.android.library plugins using a flag in gradle.properties ( isModule ).
Multi‑project scheme : Each business component is a separate Gradle project (library module) that can be built and run independently.
Example of the flag configuration:
//gradle.properties
# Component independent debugging switch
isModule = falseBuild‑script snippet to apply the appropriate plugin:
if (isModule.toBoolean()) {
apply plugin: 'com.android.application'
} else {
apply plugin: 'com.android.library'
}Dynamic configuration of applicationId and AndroidManifest.xml is also handled based on the flag.
4. Page Routing
ARouter is used for decoupled navigation. Dependencies are added in the common component:
dependencies {
api 'com.alibaba:arouter-api:1.4.0'
annotationProcessor 'com.alibaba:arouter-compiler:1.2.1'
}Example of a component activity annotated for routing:
@Route(path = "/cart/cartActivity")
public class CartActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_cart);
}
}Navigation from another component:
ARouter.getInstance()
.build("/cart/cartActivity")
.withString("key1", "value1")
.withString("key2", "value2")
.navigation();5. Component Communication via Services
Expose services through an export_cart module. Define an interface extending IProvider :
public interface ICartService extends IProvider {
CartInfo getProductCountInCart();
}Implement the service and annotate it with a route:
@Route(path = CartRouterTable.PATH_SERVICE_CART)
public class CartServiceImpl implements ICartService {
@Override
public CartInfo getProductCountInCart() {
CartInfo info = new CartInfo();
info.productCount = 666;
return info;
}
@Override
public void init(Context context) { /* optional */ }
}Utility class for other components:
public class CartServiceUtil {
public static void navigateCartPage(String p1, String p2) {
ARouter.getInstance()
.build(CartRouterTable.PATH_PAGE_CART)
.withString("key1", p1)
.withString("key2", p2)
.navigation();
}
public static ICartService getService() {
return (ICartService) ARouter.getInstance()
.build(CartRouterTable.PATH_SERVICE_CART)
.navigation();
}
public static CartInfo getCartProductCount() {
return getService().getProductCountInCart();
}
}6. Fragment Retrieval
Fragments are also obtained via ARouter:
@Route(path = CartRouterTable.PATH_FRAGMENT_CART)
public class CartFragment extends Fragment { /* ... */ }In another component:
Fragment cartFragment = (Fragment) ARouter.getInstance()
.build(CartRouterTable.PATH_FRAGMENT_CART)
.navigation();
transaction.add(R.id.container, cartFragment, "tag");
transaction.commit();7. Application Lifecycle Distribution
The AppLifecycle plugin distributes Application callbacks to components that implement IApplicationLifecycleCallbacks and are annotated with @AppLifecycle . Example component:
@AppLifecycle
public class CartApplication implements IApplicationLifecycleCallbacks {
@Override
public int getPriority() { return NORM_PRIORITY; }
@Override
public void onCreate(Context context) {
Log.i("CartApplication", "onCreate");
}
// other callbacks omitted for brevity
}Shell Application triggers the manager:
public class MyApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
ApplicationLifecycleManager.init();
ApplicationLifecycleManager.onCreate(this);
}
@Override
public void onTerminate() { ApplicationLifecycleManager.onTerminate(); }
@Override
public void onLowMemory() { ApplicationLifecycleManager.onLowMemory(); }
@Override
public void onTrimMemory(int level) { ApplicationLifecycleManager.onTrimMemory(level); }
}8. Migrating Legacy Projects
Steps include identifying base, business‑base, and business components; extracting reusable libraries into a Common module; publishing components as AARs; and gradually refactoring code to depend on export_xxx modules for navigation and services.
Common Issues
ButterKnife in library modules requires the ButterKnife Gradle plugin and the use of R2 instead of R :
buildscript {
dependencies {
classpath 'com.jakewharton:butterknife-gradle-plugin:10.2.3'
}
}
apply plugin: 'com.jakewharton.butterknife'After applying the plugin, replace @BindView(R.id.xxx) with @BindView(R2.id.xxx) .
9. Conclusion
The article covered the motivation, architecture, and practical solutions for Android componentization, including independent debugging, routing, service communication, fragment access, application lifecycle handling, and legacy migration, with concrete Gradle and ARouter code snippets.
Demo Links
Shell project: https://github.com/hufeiyang/ComponentLearning
AppLifecycle plugin: https://github.com/hufeiyang/Android-AppLifecycleMgr
Sohu Tech Products
A knowledge-sharing platform for Sohu's technology products. As a leading Chinese internet brand with media, video, search, and gaming services and over 700 million users, Sohu continuously drives tech innovation and practice. We’ll share practical insights and tech news here.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.