Android 跨Module之间的数据通信

目前无论是后端还是客户端,项目的代码结构都在朝着组件化、模块化发展。在一个Android项目中,我们通常会将一个模块的逻辑代码放在一个Module,例如Paylib、Utillib、Pushib等,项目结构如下图所示。

我们在主工程(app目录下)下导入Module就能调用Module里封装好的逻辑,会对我们后期的代码扩展、维护等带来非常大的便利,也是目前主流的编程趋势。

但是这种将一些模块的代码逻辑封装在了Module中也会带来一些问题,虽然主工程内可以调用Module内封装好的方法或者属性,但是Module内部却无法调用主工程内的数据,换句话说就是Module无法和主工程通信。

举个栗子,我们有一个Httplib库,在这个lib中我们处理一些Http请求,但是Http请求是一个耗时操作,假如我们需要一次处理n个Http请求,假如在某些特定的Http请求完毕后,我们UI需要做一些刷新或者需要做一些其他的数据处理我们应该怎么做呢?

我们肯定需要在特定Http请求完毕之后将该事件通知给主工程,让主工程做相对应的处理,那么问题就变成了Module和主工程之间的通信问题,需要怎么处理会比较好呢?我们又有哪些处理方式?

我们可选的方式有:

1.接口回调

这种方式也是比较常见的,但是会有一个问题,如果我们Module之间需要通信的地方有很多,接口也会变得很复杂,后期的维护成本也会比较大。(再次不进行代码展示,感兴趣可自行搜索)

2.广播

这种方式是最不推荐的,广播有延迟不说,并且过多的发送广播也是一种很危险的行为,在最新的Android 13中Google已经对广播做了一些限制,如果一个App频繁的发送广播是有可能会导致系统的Crash的,并且如果广播没有设置好是很容易被黑客攻击的,非常危险,非常不建议使用。

3.LiveData

熟悉Android的UU们肯定都有使用过LiveData,我也经常使用,通常做一些响应式UI刷新或者其他响应式逻辑时会用到LiveData,其实LiveData也可以来做跨Module之间的通信,实现起来也比较简单,后期维护起来也很容易。今天我们就来介绍一下我自己处理的一个LiveData来实现的跨Module的数据通信的工具

第一步,先在Module中创建一个数据通信的单例类(这个Module可以导入其他的Module,来实现Module之间的通信),代码采用Kotlin实现,这里只展示String类型的数据通信。

class CommonUtil {
    private val stringHashMap = HashMap<String, MutableLiveData<String>>()

    fun setStringLiveData(key: String, defaultValue: String) {
        stringHashMap[key] = MutableLiveData(defaultValue)
    }

    fun setValue(key: String, targetValue: String) {
        stringHashMap[key]?.value = targetValue
    }

    fun getStringLiveData(key: String): MutableLiveData<String>? {
        return try {
            stringHashMap[key]
        } catch (e: Exception) {
            throw RuntimeException("未找到key值为: $key 的MutableLiveData")
        }
    }

    companion object {
        //伴生对象,该代码块内的属性和方法都是静态类型的
        @Volatile
        private var commonUtil: CommonUtil? = null
        fun getInstance(): CommonUtil {
            return (commonUtil ?: synchronized(this) {
                commonUtil ?: CommonUtil().also {
                    commonUtil = it
                }
            })
        }
    }
}

 第二步,在Acitvity中添加对应的LiveData(尽量在ViewModel调用Repo处理,符合MVVM架构思想,这里为了简单就现在Activity中处理了)

 CommonUtil.getInstance().setStringLiveData(KEY_1, KEY_1_VALUE)

第三步,注册添加Live的Observe方法观察数据变化

 CommonUtil.getInstance().getStringLiveData(KEY_1)?.observe(this) {
            Toast.makeText(this, it, Toast.LENGTH_SHORT).show()
        }

第四步,执行lib中的数据操作,并在关键位置调用LiveData的setValue方法,回调给主工程处理(这里使用Handler来模拟Http的耗时操作,当然最好使用协程处理,这里还是为了简单)

import android.os.Handler
import android.os.Looper

object DataUtil {
    fun doSomething(key: String) {
        Handler(Looper.myLooper()!!).postDelayed({
            CommonUtil.getInstance().setValue(key, "init_data_over")
        }, 5000)
    }
}

第五步,我们就可以在主工程收到回调并展示Toast了。

末尾把Activity的所有代码都展示一下

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        CommonUtil.getInstance().setStringLiveData(KEY_1, KEY_1_VALUE)

        CommonUtil.getInstance().getStringLiveData(KEY_1)?.observe(this) {
            Toast.makeText(this, it, Toast.LENGTH_SHORT).show()
        }

        DataUtil.doSomething(KEY_1)
    }

    companion object {
        private const val KEY_1 = "live_1"
        private const val KEY_1_VALUE = "start_init"
    }
}

项目已经同步开源道Gitee,欢迎下载demo调试,如有改进意见欢迎指出。瑞思拜

HelloWorld: 跨Module数据通信Demo (gitee.com)

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值