# 组件化架构

## 目录
- [组件化概念](#组件化概念)
- [组件化优势](#组件化优势)
- [组件划分原则](#组件划分原则)
- [组件间通信](#组件间通信)
- [路由框架](#路由框架)
- [组件化实现](#组件化实现)
- [组件化最佳实践](#组件化最佳实践)
- [面试常见问题](#面试常见问题)

---

## 组件化概念

### 什么是组件化？

组件化是将一个大型应用拆分成多个独立的、可复用的组件（Module），每个组件可以独立开发、测试、编译和运行。

### 组件化架构图

```
┌─────────────────────────────────┐
│         App Module               │  ← 主应用模块
│  (依赖所有业务组件)                │
└─────────────────────────────────┘
           │
    ┌──────┴──────┐
    │             │
┌───▼───┐    ┌───▼───┐
│组件A  │    │组件B  │  ← 业务组件
│(Module)│    │(Module)│
└───┬───┘    └───┬───┘
    │             │
    └──────┬──────┘
           │
    ┌──────▼──────┐
    │  Common Module │  ← 公共组件
    │  (基础库)      │
    └──────────────┘
```

### 组件类型

1. **App Module**：主应用模块，依赖所有业务组件
2. **业务组件**：独立的功能模块（如登录、首页、个人中心）
3. **基础组件**：公共库（网络、图片加载、工具类等）

---

## 组件化优势

### 1. 独立开发

- 每个组件可以独立开发、测试
- 不同团队可以并行开发不同组件
- 减少代码冲突

### 2. 代码复用

- 组件可以在多个项目中使用
- 减少重复代码
- 提高开发效率

### 3. 按需加载

- 可以按需加载组件
- 减少 APK 体积
- 提升启动速度

### 4. 易于维护

- 组件职责清晰
- 修改影响范围小
- 便于定位问题

### 5. 团队协作

- 团队可以独立负责不同组件
- 减少沟通成本
- 提高开发效率

---

## 组件划分原则

### 1. 按业务功能划分

```
app/
├── app/                    # 主应用模块
├── module_login/           # 登录组件
├── module_home/            # 首页组件
├── module_user/            # 用户中心组件
├── module_order/           # 订单组件
└── common/                 # 公共组件
    ├── common_base/        # 基础库
    ├── common_network/     # 网络库
    └── common_ui/          # UI 组件库
```

### 2. 单一职责原则

- 每个组件只负责一个业务功能
- 组件之间低耦合
- 组件内部高内聚

### 3. 依赖关系清晰

```
App Module
    ↓
业务组件（相互独立）
    ↓
基础组件
```

### 4. 组件粒度适中

- **过细**：组件过多，管理复杂
- **过粗**：组件过大，失去组件化意义
- **适中**：按业务功能合理划分

---

## 组件间通信

### 1. 接口通信

```java
// 定义接口
public interface ILoginService {
    void login(String username, String password, Callback callback);
    boolean isLogin();
    void logout();
}

// 组件A实现接口
public class LoginServiceImpl implements ILoginService {
    @Override
    public void login(String username, String password, Callback callback) {
        // 登录逻辑
    }
}

// 组件B使用接口
public class HomeActivity extends AppCompatActivity {
    private ILoginService loginService;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        loginService = ServiceLoader.load(ILoginService.class);
        if (loginService.isLogin()) {
            // 已登录
        }
    }
}
```

### 2. 事件总线通信

```java
// 使用 EventBus
public class LoginEvent {
    private boolean isLogin;
    
    public LoginEvent(boolean isLogin) {
        this.isLogin = isLogin;
    }
}

// 组件A发送事件
EventBus.getDefault().post(new LoginEvent(true));

// 组件B接收事件
@Subscribe(threadMode = ThreadMode.MAIN)
public void onLoginEvent(LoginEvent event) {
    if (event.isLogin()) {
        // 处理登录事件
    }
}
```

### 3. 路由通信

```java
// 使用 ARouter
// 组件A跳转到组件B
ARouter.getInstance()
    .build("/user/profile")
    .withString("userId", "123")
    .navigation();

// 组件B接收参数
@Route(path = "/user/profile")
public class ProfileActivity extends AppCompatActivity {
    @Autowired
    String userId;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ARouter.getInstance().inject(this);
        // 使用 userId
    }
}
```

### 4. 服务发现

```java
// 使用 ServiceLoader
public class ServiceManager {
    private static ServiceManager instance;
    private Map<Class, Object> services = new HashMap<>();
    
    public static ServiceManager getInstance() {
        if (instance == null) {
            synchronized (ServiceManager.class) {
                if (instance == null) {
                    instance = new ServiceManager();
                }
            }
        }
        return instance;
    }
    
    public <T> void register(Class<T> clazz, T service) {
        services.put(clazz, service);
    }
    
    public <T> T get(Class<T> clazz) {
        return (T) services.get(clazz);
    }
}

// 组件A注册服务
ServiceManager.getInstance().register(ILoginService.class, new LoginServiceImpl());

// 组件B获取服务
ILoginService loginService = ServiceManager.getInstance().get(ILoginService.class);
```

---

## 路由框架

### ARouter 使用

#### 1. 集成 ARouter

```gradle
// build.gradle
android {
    defaultConfig {
        javaCompileOptions {
            annotationProcessorOptions {
                arguments = [AROUTER_MODULE_NAME: project.getName()]
            }
        }
    }
}

dependencies {
    implementation 'com.alibaba:arouter-api:1.5.1'
    annotationProcessor 'com.alibaba:arouter-compiler:1.5.1'
}
```

#### 2. 初始化

```java
// Application
public class MyApplication extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        if (BuildConfig.DEBUG) {
            ARouter.openLog();
            ARouter.openDebug();
        }
        ARouter.init(this);
    }
}
```

#### 3. 定义路由

```java
// 组件A：登录页面
@Route(path = "/login/activity")
public class LoginActivity extends AppCompatActivity {
    // ...
}

// 组件B：用户中心
@Route(path = "/user/profile")
public class ProfileActivity extends AppCompatActivity {
    @Autowired
    String userId;
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ARouter.getInstance().inject(this);
    }
}
```

#### 4. 路由跳转

```java
// 普通跳转
ARouter.getInstance()
    .build("/login/activity")
    .navigation();

// 带参数跳转
ARouter.getInstance()
    .build("/user/profile")
    .withString("userId", "123")
    .withInt("age", 25)
    .navigation();

// 带回调跳转
ARouter.getInstance()
    .build("/user/profile")
    .navigation(this, new NavCallback() {
        @Override
        public void onArrival(Postcard postcard) {
            // 到达目标页面
        }
        
        @Override
        public void onFound(Postcard postcard) {
            // 找到目标页面
        }
        
        @Override
        public void onLost(Postcard postcard) {
            // 未找到目标页面
        }
    });
```

#### 5. 路由拦截器

```java
@Interceptor(priority = 1, name = "login")
public class LoginInterceptor implements IInterceptor {
    @Override
    public void process(Postcard postcard, InterceptorCallback callback) {
        if (postcard.getPath().equals("/user/profile")) {
            if (!isLogin()) {
                // 未登录，跳转到登录页
                ARouter.getInstance()
                    .build("/login/activity")
                    .navigation();
                callback.onInterrupt(new RuntimeException("请先登录"));
            } else {
                callback.onContinue(postcard);
            }
        } else {
            callback.onContinue(postcard);
        }
    }
    
    @Override
    public void init(Context context) {
        // 初始化
    }
}
```

---

## 组件化实现

### 1. 项目结构

```
project/
├── app/                    # 主应用模块
│   └── build.gradle
├── module_login/           # 登录组件
│   └── build.gradle
├── module_home/            # 首页组件
│   └── build.gradle
├── module_user/            # 用户中心组件
│   └── build.gradle
├── common/                 # 公共组件
│   ├── common_base/        # 基础库
│   ├── common_network/     # 网络库
│   └── common_ui/         # UI 组件库
└── build.gradle           # 项目配置
```

### 2. build.gradle 配置

```gradle
// 项目 build.gradle
buildscript {
    repositories {
        google()
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:4.1.0'
        classpath 'com.alibaba:arouter-register:1.0.2'
    }
}

// app/build.gradle
dependencies {
    if (isModule.toBoolean()) {
        // 组件化模式：依赖各个业务组件
        implementation project(':module_login')
        implementation project(':module_home')
        implementation project(':module_user')
    }
    // 依赖公共组件
    implementation project(':common:common_base')
    implementation project(':common:common_network')
}

// module_login/build.gradle
android {
    if (isModule.toBoolean()) {
        // 组件化模式：作为 Library
        apply plugin: 'com.android.library'
    } else {
        // 独立模式：作为 Application
        apply plugin: 'com.android.application'
    }
}

dependencies {
    // 依赖公共组件
    implementation project(':common:common_base')
    implementation project(':common:common_network')
}
```

### 3. gradle.properties 配置

```properties
# 是否组件化模式
isModule=false

# 组件化模式：true（作为 Library）
# 独立模式：false（作为 Application）
```

### 4. AndroidManifest 配置

```xml
<!-- app/src/main/AndroidManifest.xml -->
<manifest>
    <application>
        <!-- 主应用配置 -->
    </application>
</manifest>

<!-- module_login/src/main/AndroidManifest.xml -->
<manifest>
    <application>
        <!-- 登录组件配置 -->
    </application>
</manifest>

<!-- module_login/src/main/AndroidManifest_debug.xml（独立模式） -->
<manifest>
    <application
        android:name=".LoginApplication"
        android:label="@string/app_name">
        <activity
            android:name=".LoginActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
</manifest>
```

### 5. 组件 Application

```java
// 组件独立 Application
public class LoginApplication extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        // 组件初始化
    }
}

// 主应用 Application
public class MainApplication extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        // 初始化公共组件
        initCommon();
        
        // 初始化业务组件
        if (BuildConfig.IS_MODULE) {
            initModules();
        }
    }
    
    private void initModules() {
        // 初始化各个业务组件
    }
}
```

---

## 组件化最佳实践

### 1. 组件依赖规则

```
业务组件 → 基础组件
App Module → 所有组件
业务组件之间不相互依赖
```

### 2. 资源命名规范

```xml
<!-- 使用组件前缀避免冲突 -->
<!-- module_login -->
<string name="login_title">登录</string>
<color name="login_bg">#FFFFFF</color>

<!-- module_home -->
<string name="home_title">首页</string>
<color name="home_bg">#FFFFFF</color>
```

### 3. 接口定义

```java
// 在 common_base 中定义接口
public interface ILoginService {
    void login(String username, String password, Callback callback);
}

// 在 module_login 中实现接口
public class LoginServiceImpl implements ILoginService {
    // 实现
}

// 在 App Module 中注册
ServiceManager.getInstance().register(ILoginService.class, new LoginServiceImpl());
```

### 4. 组件测试

```java
// 每个组件可以独立运行和测试
// 在独立模式下，组件可以作为独立应用运行
if (!isModule.toBoolean()) {
    // 独立模式配置
}
```

### 5. 版本管理

```gradle
// 统一管理版本号
ext {
    compileSdkVersion = 30
    minSdkVersion = 21
    targetSdkVersion = 30
    versionCode = 1
    versionName = "1.0.0"
}
```

---

## 面试常见问题

### Q1: 什么是组件化？

**答案：**
组件化是将一个大型应用拆分成多个独立的、可复用的组件（Module），每个组件可以独立开发、测试、编译和运行。

### Q2: 组件化的优势？

**答案：**
1. 独立开发：每个组件可以独立开发、测试
2. 代码复用：组件可以在多个项目中使用
3. 按需加载：可以按需加载组件
4. 易于维护：组件职责清晰
5. 团队协作：团队可以独立负责不同组件

### Q3: 如何划分组件？

**答案：**
1. 按业务功能划分
2. 单一职责原则
3. 依赖关系清晰
4. 组件粒度适中

### Q4: 组件间如何通信？

**答案：**
1. 接口通信：定义接口，组件实现接口
2. 事件总线：使用 EventBus 等事件总线
3. 路由通信：使用 ARouter 等路由框架
4. 服务发现：使用 ServiceLoader 等服务发现机制

### Q5: ARouter 的作用？

**答案：**
ARouter 是阿里巴巴开源的 Android 路由框架，用于：
1. 页面跳转：组件间页面跳转
2. 参数传递：页面间参数传递
3. 拦截器：路由拦截和权限控制
4. 服务发现：组件间服务调用

### Q6: 组件化的最佳实践？

**答案：**
1. 组件依赖规则：业务组件 → 基础组件
2. 资源命名规范：使用组件前缀
3. 接口定义：在公共组件中定义接口
4. 组件测试：每个组件可以独立测试
5. 版本管理：统一管理版本号

---

## 总结

组件化是大型 Android 应用架构的重要方式，通过将应用拆分成多个独立组件，可以实现独立开发、代码复用、易于维护等优势。在实际项目中，需要合理划分组件、设计组件间通信机制、使用路由框架等。

---

*最后更新：2024年*
