Mobile Development 32 min read

Android Componentization: Architecture, Independent Debugging, Routing, and Communication

This article explains how to transform a large Android project into a componentized architecture by modularizing code, configuring Gradle for independent debugging, using ARouter for page navigation and service communication, handling fragment instances, distributing Application lifecycle events, and migrating legacy projects.

Sohu Tech Products
Sohu Tech Products
Sohu Tech Products
Android Componentization: Architecture, Independent Debugging, Routing, and Communication

Background – As an Android project expands, developers face long compile times, frequent merge conflicts, unclear module responsibilities, and extensive regression testing, indicating the need for componentization.

Understanding modularization – In Android Studio, each module corresponds to a functional unit; splitting the app into multiple modules (e.g., Home, Category, Cart, My, Detail) reduces coupling and improves maintainability.

Componentization advantages – Decoupling modules into independent business components speeds up compilation, improves collaboration, and enables reusable functionality similar to third‑party libraries.

Independent debugging

Two approaches are provided:

Single‑project solution – Dynamically switch a module between com.android.application and com.android.library plugins using a flag in gradle.properties :

# gradle.properties
isModule = false
if (isModule.toBoolean()) {
    apply plugin: 'com.android.application'
} else {
    apply plugin: 'com.android.library'
}

Application ID and manifest are also switched based on the flag:

android {
    defaultConfig {
        if (isModule.toBoolean()) {
            applicationId "com.hfy.componentlearning.cart"
        }
    }
    sourceSets {
        main {
            if (isModule.toBoolean()) {
                manifest.srcFile 'src/main/moduleManifest/AndroidManifest.xml'
            } else {
                manifest.srcFile 'src/main/AndroidManifest.xml'
            }
        }
    }
}

Multi‑project solution – Each business component is built as a separate library module (ARR) and published to a Maven repository (private or JitPack). The host "shell" project depends on these ARR packages, keeping code isolation and allowing independent development.

ARouter for page routing

Common component adds the ARouter dependencies:

dependencies {
    api 'com.alibaba:arouter-api:1.4.0'
    annotationProcessor 'com.alibaba:arouter-compiler:1.2.1'
}

Each activity or fragment is annotated with a route path, e.g.:

@Route(path = "/cart/cartActivity")
public class CartActivity extends AppCompatActivity { ... }

Navigation is performed via:

ARouter.getInstance()
    .build("/cart/cartActivity")
    .withString("key1", "value1")
    .navigation();

Component communication via services

Export modules define service interfaces that extend IProvider . Example service interface:

public interface ICartService extends IProvider {
    CartInfo getProductCountInCart();
}

Implementation is annotated with a route and provides the logic:

@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 simplifies usage:

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();
    }
}

Home component consumes the service without depending on the Cart module directly.

Fragment instance acquisition

Fragments are also routed via ARouter:

@Route(path = CartRouterTable.PATH_FRAGMENT_CART)
public class CartFragment extends Fragment { ... }

Host activity obtains the fragment:

Fragment cartFragment = (Fragment) ARouter.getInstance()
    .build(CartRouterTable.PATH_FRAGMENT_CART).navigation();
transaction.add(R.id.fl_test_fragment, cartFragment, "tag");

Application lifecycle distribution

The AppLifecycle plugin collects classes annotated with @AppLifecycle that implement IApplicationLifecycleCallbacks . Example:

@AppLifecycle
public class CartApplication implements IApplicationLifecycleCallbacks {
    @Override
    public int getPriority() { return NORM_PRIORITY; }
    @Override
    public void onCreate(Context context) { /* init */ }
    // other callbacks omitted
}

Shell app initializes the manager in Application :

ApplicationLifecycleManager.init();
ApplicationLifecycleManager.onCreate(this);

All components receive lifecycle callbacks without the shell needing to know them.

Legacy project migration

The article outlines a step‑by‑step approach: identify base, business‑base, and business components; extract common utilities into a Common module; publish each component as an ARR; handle issues such as ButterKnife R2 usage by applying the ButterKnife Gradle plugin.

Conclusion

Componentization, combined with ARouter and the AppLifecycle plugin, provides a scalable solution for large Android codebases, enabling faster builds, clear module boundaries, independent debugging, and clean inter‑module communication.

ModularizationandroidGradlecomponentizationDependencyInjectionARouter
Sohu Tech Products
Written by

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.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.