之前呢,也做过一个关于模块化业务分离的架构方案,这篇帖子想分享一下关于模块间的数据交互的方案。模块化架构,基础的可以通过创建多个module来把业务进行区分和代码的解耦。为了解耦,让module可拆卸,可移植,那么业务模块间是不会有任何的依赖和引用的,在这样的情况下,我们如何才能让模块间联系起来,进行数据交互呢。
下面来对我项目的思路做个概述。
1.涉及框架
路由框架, 用路由框架,通过url的形式查找具体的service实现类,从而执行相关操作。目的就是为了做到在没有任何模块间依赖和引用的情况下实现向上转型。(我使用的是阿里的Arouter)
2.实现思路
第一,我们的模块化项目一定在纵向上有分层,比如从下到上有base模块,业务模块,和app入口模块。所有业务模块都有base模块的依赖,但业务模块之间没有任何引用和依赖。
第二,从base模块入手,建立base service接口,base service实现基类。接口中要可提供callback,以供给调用者设置回调接口。实现基类需要拿到调用者设置的回调接口,以在完成逻辑操作后将数据进行回传。
第三,在base模块中,建立service接口并继承base service接口,编写提供给调用者使用的方法,参数由负责不同业务的同事进行商讨决定。
第四,在对应业务模块中,建立service实现类并继承base service实现基类,并且implements对应的service接口,去实现方法的具体逻辑。
完成以上四步,编码工作就基本结束,就可以提供给开发者进行业务代码编写了。下面呢,我就通过代码的形式,将这四步操作再来描述一遍,并且举个例子。
3.代码走起
首先,第一步就没有什么代码可展示了,只要你的项目架构有纵向分层就可以了。
第二步,来创建我们的service接口基类,service实现基类。
先创建一个ServiceCallBack接口作为数据回调的载体监听,并加上泛型。
public interface ServiceCallBack<T> {
void callBack(T t);
}
创建BaseIService继承IProvider。IProvider是ARouter框架中的一个基类接口,对我们这个交互思路没有太大参与,大家都这么用,那么我也这么用。然后BaseIService中,创建getDataBack方法,以用于调用者去设置回调监听。创建setDataBack用于被调用者去将数据进行回传。
public interface BaseIService<T> extends IProvider{
void getDataBack(ServiceCallBack serviceCallBack);
void setDataBack(T t);
}
public class BaseService<T> implements BaseIService<T> {
protected ServiceCallBack serviceCallBack;
@Override
public void getDataBack(ServiceCallBack serviceCallBack) {
this.serviceCallBack = serviceCallBack;
}
@Override
public void init(Context context) {
}
@Override
public void setDataBack(T t) {
if (null != serviceCallBack) {
serviceCallBack.callBack(t);
}
}
}
基类编写完成之后,下面写一个test接口,和test逻辑实现类来展示一下如何使用。
在base模块中,创建ITestService接口并继承BaseIService。并创建doSomething方法提供给调用者进行调用。
public interface ITestService extends BaseIService{
void doSomeThing(String string);
}
加入现在有业务A模块,业务B模块,调用者是业务A模块的同事,想要调用业务B的一些业务。那么在业务B模块中需要创建实现类。创建TestService类,继承BaseService,并实现ITestService接口。并使用@Route注解对类进行修饰,后期将通过url的形式去把实现类做向上转型操作。
@Route(path = "/test/service")
public class TestService extends BaseService implements ITestService {
@Override
public void doSomeThing(String string) {
}
}
实现类创建好后,就可以在对应的方法中去编辑具体的业务逻辑,比如打开一个选择页面等等。下面来编辑一下,我们先来个简单的例子。当调用了doSomeThing之后,也回传一条字符串。
@Route(path = "/test/service")
public class TestService extends BaseService implements ITestService {
@Override
public void doSomeThing(String string) {
getDataBack(stirng + "000");
}
}
实现类编辑好之后,就需要看一下如何调用其他模块的逻辑。在业务A模块中,需要调用的位置,先要通过url去找到对应实现类并做向上转型。为什么要做向上转型,是因为业务A模块与业务B模块之间并没有依赖和引用,所以业务A模块中并不会得到TestService的引用,只能向上转型为base模块中的TestIService。(看infor_screen_button的点击逻辑)
@OnClick({R.id.infor_screen_button, R.id.infor_call_button, R.id.infor_add_button})
public void onViewClicked(View view) {
switch (view.getId()) {
case R.id.infor_screen_button:
ITestService service = (ITestService) ARouter.getInstance().build("/test/service").navigation();
service.getDataBack(new ServiceCallBack<String>() {
@Override
public void callBack(String s) {
Toast.makeText(mContext,s,Toast.LENGTH_SHORT).show();
}
});
service.doSomeThing("test1");
break;
case R.id.infor_call_button:
break;
case R.id.infor_add_button:
openDialog();
break;
}
}
首先,根据url找到实现类并做向上转型。
ITestService service = (ITestService) ARouter.getInstance().build("/test/service").navigation();
然后,调用getDataBack来设置回调监听,记得最好加上泛型。其中泛型是由业务A模块和业务B模块两方开发人员商讨决定的。并且在callBack方法中编写数据回传后的业务处理逻辑。
service.getDataBack(new ServiceCallBack<String>() {
@Override
public void callBack(String s) {
Toast.makeText(mContext,s,Toast.LENGTH_SHORT).show();
}
});
最后调用接口的doSomeThing方法。
service.doSomeThing("test1");
最终效果就是当点击按钮的时候,就会弹出一个test1000内容的吐司。那么一个简单的数据交互就实现了。但是,此时就问了,如果我调用其他业务的逻辑并非马上就能回传数据,而是在一些操作后才有数据回传呢?那么下面就再举个例子,来展示一下这种情况下代码如何编写。
重新编辑一下业务B模块中的TestService实现类中的doSomeThing方法。
这次就不是直接进行数据回传了,而是打开了业务B模块中的一个页面,在页面中做了一些操作之后才进行数据回传。
@Route(path = "/test/service")
public class TestService extends BaseService implements ITestService {
@Override
public void doSomeThing(String string) {
ARouter.getInstance().build("/testa/testa").withString("testStr",string).navigation();
}
}
那么来看下在页面中在操作之后如何把数据回传回去。当点击了between_modules_button的按钮之后,表示执行了一个业务逻辑,然后通过url把实现类找到并作向上转型,通过service的setDataBack方法就可以将数据进行回传了。
} else if (i == R.id.between_modules_button) {//模块间功能调用
ITestService service = (ITestService) ARouter.getInstance().build("/test/service").navigation();
service.setDataBack(testStr + "000");
finish();
} else if (i == R.id.arouter_fin
那么,这样一来,就可以在不同模块之间进行数据交互了。如果有不好的地方希望大家可以给些建议,如果文章能够帮助到你,那就再好不过了。