项目作者: zongwu233

项目描述 :
Decoupled protocol for modules in Android App
高级语言: Java
项目地址: git://github.com/zongwu233/Summer.git
创建时间: 2017-03-05T08:07:48Z
项目社区:https://github.com/zongwu233/Summer

开源协议:MIT License

下载


Summer

介绍

Summer是一个模块解耦框架,它解决了以下几个痛点:

1、模块与模块之间不再需要相互依赖

2、模块边界清晰化

使用

模块A

  • 在build.gradle加入
  1. compile 'com.meiyou:summer:1.0.4'
  2. compile 'com.meiyou:summer-compiler:1.0.4'
  • 定义接口:
  1. @ProtocolShadow("ModuleBarStub")
  2. public interface ModuleStub {
  3. public void testMethod(String msg, Context context, TextView textView);
  4. }

其中:

ProtocolShadow 是summer接口标识,意味着在编译时会被扫描到并做相应的处理

ModuleBarStub 则是协商的名字,模块B将使用这个字符串标识与之联系

模块B

  • 在build.gradle加入
  1. compile 'com.meiyou:summer:1.0.4'
  2. compile 'com.meiyou:summer-compiler:1.0.4'
  • 定义实现:
  1. @Protocol("ModuleBarStub")
  2. public class ModuleBar {
  3. public void testMethod(String msg, Context context,
  4. TextView textView) {
  5. Toast.makeText(context, msg, Toast.LENGTH_SHORT).show();
  6. }
  7. }

其中:

Protocol 是summer实现标识,意味着在编译时会被扫描到并做相应的处理

ModuleBarStub 则是与模块A协商的名字

  • 模块B调用模块A的方法:
  1. ProtocolInterpreter.getDefault().
  2. create(ModuleStub.class)
  3. .testMethod("oh this from main Activity!",
  4. getApplicationContext(), textView);

至此,模块A和模块B,在不相互依赖的情况下,完成了交互。

实现原理

通过编译期注解+java动态代理实现。
具体细节见代码。

缺点

之前可以通过implements interface 比较方便地获得子类方法的签名,现在没有IDE智能提示,写实际的实现类方法的时候,有点不方便。

混淆

-keep public class com.meiyou.framework.summer.data.* { ; }

提供模块间数据总线功能

提供类似于EventBus 的功能,但是属于模块间可用(也支持模块内自己通信)。用法类似于EventBus。除了要注意:

发送消息的模块,要对Event 的class做注解@Event(“name”)

在响应消息的模块的具体方法上,对方法注解@OnEvent(“name”)即可,方法名称不受限制,但是改方法的入参,必须与原始Event的class同构。

同构:具有相同的结构组成;相同的成员变量。

OnEvent注解支持MainThread和BackgroundThread。
示例:

事件源Event:

  1. @Event("Account")
  2. public class AccountDO {
  3. String nick = "ooooh";
  4. long userId = 2222;
  5. public AccountDO(String nick, long userId) {
  6. this.nick = nick;
  7. this.userId = userId;
  8. }
  9. public String getNick() {
  10. return nick;
  11. }
  12. public void setNick(String nick) {
  13. this.nick = nick;
  14. }
  15. public long getUserId() {
  16. return userId;
  17. }
  18. public void setUserId(long userId) {
  19. this.userId = userId;
  20. }
  21. }

接收改事件的对象需要注册,比如:

  1. ProtocolInterpreter.getDefault().register(testEvent);

多次调用该方法会自动去重,也可以调用下面方法检测是否已经注册:

  1. boolean registered = ProtocolInterpreter.getDefault().isRegister(testEvent);

发送该事件(可以在任何活动线程执行):

  1. ProtocolInterpreter.getDefault().post(new AccountDO("bg", 2222));

testEvent 的class里面有:

  1. @OnEvent("Account")
  2. public void process(MyAccount account) {
  3. ToastUtils.showToast(mContext,"module test get: "+account.getNick() + "," + account.getUserId());
  4. }
  5. @OnEvent(value = "Account",exec = OnEvent.Thread.BACK_GROUND)
  6. public void process2(MyAccount account) {
  7. LogUtils.d(TAG,"module test background get: "+account.getNick() + "," + account.getUserId());
  8. }

process() process2() 两个方法注册接收改事件,分别是在MainThread BackgroundThread里执行。

如果不指定OnEvent里的exec就意味着默认在mainThread执行。

License MIT