Android组件化 -> 不同Module之间的通信(接口下沉实现)

在Android组件化开发中,模块间通信是一个关键问题。本文将介绍如何通过接口下沉的方式实现不同Module之间的松耦合通信,以提高代码的可维护性和可扩展性。

项目Module依赖结构

首先,让我们了解一下本文讨论的项目Module依赖结构:

app
 ├── lib_ai_extend (依赖lib_canvas_render)
 ├── lib_filter (依赖lib_opengl_render)
 ├── lib_canvas_render (依赖lib_common)
 ├── lib_opengl_render (依赖lib_common)
 └── lib_common (基础组件)

图形化依赖关系:

                  ┌─────────┐
                  │   App   │
                  └────┬────┘
           ┌────────────┴────────────┐
     ┌─────▼─────┐           ┌───────▼─────┐
     │lib_filter │           │lib_ai_extend│
     └─────┬─────┘           └───────┬─────┘
┌──────────▼───────────┐  ┌──────────▼────────────┐
│  lib_opengl_render   │  │   lib_canvas_render   │
└──────────┬───────────┘  └──────────┬────────────┘
           │                         │
           └─────────┐  ┌────────────┘
                ┌────▼──▼─────┐
                │  lib_common │
                └─────────────┘

接口下沉实现通信的核心思想

接口下沉的核心思想是:将接口定义放在底层公共模块中,具体实现放在上层业务模块中。这样可以实现:

  • 下层模块定义接口,上层模块实现接口
  • 各模块通过接口而非具体实现类进行通信
  • 避免循环依赖问题

实现步骤

1. 在lib_common基础组件中定义接口

首先,在基础组件lib_common中定义各个功能模块的接口:

object ServiceFactory {
    // lib_ai_extend的服务接口
    interface LibAIExtendService {
        fun LibAIExtendServiceMethod()
    }

    // lib_filter的服务接口
    interface LibFilterService {
        fun LibFilterServiceMethod()
    }

    interface RouterService {
        // Fragment注册
        fun registerFragment(path: String, fragmentClass: Class<out Fragment>)

        // Fragment切换
        fun routerFragment(fragmentManager: FragmentManager?, containerId: Int, path: String, bundle: Bundle? = null)

        // 直接切换Fragment实例
        fun replaceFragment(fragmentManager: FragmentManager?, containerId: Int, fragment: Fragment)
    }
}

2. 在lib_common基础组件创建服务管理器

lib_common模块中创建一个服务管理器,用于注册和获取各个模块的服务实现:

// 服务管理类,单例实现
class ServiceManager private constructor() : ServiceProvider {

    companion object {
        // 单例实例
        @Volatile
        private var instance: ServiceManager? = null

        // 获取单例实例
        fun getInstance(): ServiceManager {
            return instance ?: synchronized(this) {
                instance ?: ServiceManager().also { instance = it }
            }
        }
    }

    private val services = mutableMapOf<Class<*>, Any>()

    override fun <T : Any> getService(serviceClass: Class<T>): T? {
        return services[serviceClass] as? T?
    }

    override fun <T : Any> addService(serviceClass: Class<T>, implementation: T) {
        if (services.containsKey(serviceClass)) {
            throw IllegalArgumentException("Service ${serviceClass.simpleName} already registered.")
        }
        services[serviceClass] = implementation
    }

    override fun <T : Any> removeService(serviceClass: Class<T>) {
        if (!services.containsKey(serviceClass)) {
            throw IllegalArgumentException("Service ${serviceClass.simpleName} not registered.")
        }
        services.remove(serviceClass)
    }
}

3. 在各业务组件中实现接口

在各个功能模块中实现lib_common中定义的接口:

// 在lib_ai_extend业务组件中实现业务接口
class LibAIExtendServiceImpl : ServiceFactory.LibAIExtendService{
    override fun LibAIExtendServiceMethod() {
        Log.d("yang", "LibAIExtendServiceMethod")
    }
}

// 在lib_filter业务组件中实现业务接口
class LibFilterServiceImpl : LibFilterService {
    override fun LibFilterServiceMethod() {
        Log.d("yang", "LibFilterServiceMethod")
    }
}

// 在lib_common基础组件中实现路由接口
class RouterServiceImpl : RouterService {
    // 日志TAG
    private val TAG = "yang"

    // 路由表映射
    private val fragmentRouteMap = mutableMapOf<String, Class<out Fragment>>()

    // 注册Fragment路由表
    override fun registerFragment(path: String, fragmentClass: Class<out Fragment>) {
        fragmentRouteMap[path] = fragmentClass
    }

    // 通过路径切换Fragment
    override fun routerFragment(
        fragmentManager: FragmentManager?,
        containerId: Int,
        path: String,
        bundle: Bundle?
    ) {
        val fragmentClass = fragmentRouteMap[path] ?: run {
            Log.e(TAG, "No fragment found for path: $path")
            return
        }

        try {
            val fragment = fragmentClass.getDeclaredConstructor().newInstance()
            bundle?.let { fragment.arguments = it }
            replaceFragment(fragmentManager, containerId, fragment)
        } catch (e: Exception) {
            Log.e(TAG, "Failed to instantiate fragment for path: $path", e)
        }
    }


    override fun replaceFragment(
        fragmentManager: FragmentManager?,
        containerId: Int,
        fragment: Fragment
    ) {
        Log.e("yang", "replaceFragment containerId: $containerId, fragment : ${fragment::class.java.simpleName}")
        val transaction = fragmentManager?.beginTransaction()
        transaction?.replace(containerId, fragment)
        transaction?.commitAllowingStateLoss()
    }
}

4. 在壳App模块中初始化服务

App模块的Application类中初始化并注册各个服务:

class MainApp : Application(){
    
    override fun onCreate() {
        super.onCreate()
        initRouterService()
        initFilterModule()
        initAIExtendModule()
    }
}


fun initFilterModule(){
    ServiceManager.getInstance().addService(LibFilterService::class.java, LibFilterServiceImpl())
    ServiceManager.getInstance().getService(RouterService::class.java)?.apply {
        registerFragment(RouterPath.FRAGMENT_FILTER, FilterFragment::class.java)
    }
}

fun initAIExtendModule(){
    ServiceManager.getInstance().addService(LibAIExtendService::class.java, LibAIExtendServiceImpl())
}

fun initRouterService(){
    ServiceManager.getInstance().addService(RouterService::class.java, RouterServiceImpl())
}

5. 壳App模块和没有依赖关系的业务模块,进行页面跳转和方法调用

// 页面跳转,通过路由服务跳转注册过的Fragment
val routerServiceImpl = ServiceManager.getInstance().getService(RouterService::class.java)

class RouterServiceImpl : RouterService {
    // 日志TAG
    private val TAG = "yang"

    // 路由表映射
    private val fragmentRouteMap = mutableMapOf<String, Class<out Fragment>>()

    // 注册Fragment路由表
    override fun registerFragment(path: String, fragmentClass: Class<out Fragment>) {
        fragmentRouteMap[path] = fragmentClass
    }

    // 通过路径切换Fragment
    override fun routerFragment(
        fragmentManager: FragmentManager?,
        containerId: Int,
        path: String,
        bundle: Bundle?
    ) {
        val fragmentClass = fragmentRouteMap[path] ?: run {
            Log.e(TAG, "No fragment found for path: $path")
            return
        }

        try {
            val fragment = fragmentClass.getDeclaredConstructor().newInstance()
            bundle?.let { fragment.arguments = it }
            replaceFragment(fragmentManager, containerId, fragment)
        } catch (e: Exception) {
            Log.e(TAG, "Failed to instantiate fragment for path: $path", e)
        }
    }


    override fun replaceFragment(
        fragmentManager: FragmentManager?,
        containerId: Int,
        fragment: Fragment
    ) {
        Log.e("yang", "replaceFragment containerId: $containerId, fragment : ${fragment::class.java.simpleName}")
        val transaction = fragmentManager?.beginTransaction()
        transaction?.replace(containerId, fragment)
        transaction?.commitAllowingStateLoss()
    }
}
// 方法调用,通过业务服务实现类,调用业务组件暴露的方法
ServiceManager.getInstance().getService(ServiceFactory.LibAIExtendService::class.java)?.apply {
    LibAIExtendServiceMethod()
}

ServiceManager.getInstance().getService(ServiceFactory.LibFilterService::class.java)?.apply {
    LibFilterServiceMethod()
}

接口下沉实现的优势

  • 解耦合:上层模块只依赖接口,不依赖具体实现,降低了模块间的耦合度
  • 避免循环依赖:通过将接口下沉到公共模块,避免了模块间的循环依赖问题
  • 灵活替换:可以轻松替换模块的具体实现,而不影响其他模块
  • 便于测试:可以轻松模拟接口实现,便于单元测试
  • 并行开发:不同团队可以并行开发不同模块,只需遵循接口约定
    注意事项
  • 接口设计要稳定:接口一旦定义,变更成本较高,需要谨慎设计
  • 避免接口爆炸:不要为每个小功能都定义接口,应该按照业务领域合理划分
  • 初始化顺序:要注意服务注册和使用的顺序,确保在使用前已完成注册
  • 考虑懒加载:对于不常用的服务,可以考虑懒加载方式,减少启动时间
  • 错误处理:服务获取失败时需要有合理的错误处理机制

总结

接口下沉是Android组件化架构中实现模块间通信的有效方式。通过在公共基础模块中定义接口,在上层模块中实现接口,并使用服务管理器进行统一管理,可以实现模块间的松耦合通信,提高代码的可维护性和可扩展性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值