在项目中我们随着功能越做越多,工程会越来越大,随之而来的我们会将某一功能单独提取出来作为一个模块,但是我们有希望这个模块是独立的,不要和其他模块相互引用,每个模块的代码不要引入在其他模块。
为了解偶我们想到接口的方式,每个模块提供一套接口出来,其他模块需要用到这个功能可以通过接口来调用,达到解偶的目的。先看一下项目结构:
包含了modleA,modleB,basic,floatview等模块而除了basic之外其他模块里面都有一个interface工程,那么他们之间的引用关系是怎样的呢?
看一张图:
app模块只依赖basic以及接口:
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
implementation project(path: ':basic')
implementation project(path: ':audioplayer::modelinterface')
implementation project(path: ':modlea:modelinterface')
implementation project(path: ':modleb:modelinterface')
implementation project(path: ':floatview:modelinterface')
}
每个模块只需要依赖basic以自己的接口工程:
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'androidx.appcompat:appcompat:1.1.0'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
implementation project(path: ':basic')
implementation project(path: ':modlea:modelinterface')
}
每个模块提供接口桥出来,每个模块实现这些接口,这些接口实现类都继承一个基础的BaseModule如:
public class IModleAPluginImpl extends BaseModule implements IModleAPlugin{
private String TAG="IModleAPluginImpl";
@Override
public void initModleA() {
Log.d(TAG,"init modle A");
}
}
public class IModleBPluginImpl extends BaseModule implements IModleBPlugin {
public String TAG="IModleBPluginImpl";
@Override
public void initModleB() {
Log.d(TAG,"init modle B");
}
}
我们怎么来管理这些接口呢,先看basic基础库怎么处理,有一个模块管理接口IModuleManager
public interface IModuleManager {
String TAG = "ModuleManager";
int RLT_OK = 0;
BaseModule getModule(String tag);
/**
* 添加模块,并初始化模块
* @param tag
* @param moduleImplCls
* @return
*/
boolean registerModule(String tag, Class> moduleImplCls);
boolean hasLoadModule(String tag);
}
ModuleManager管理类:
/**
* 模块管理
*/
public class ModleManager implements IModuleManager {
/**
* 预加载模块
*/
private Map mModuleLoadClassMap = new ConcurrentHashMap<>();
/**
* 正常时间加载的模块
*/
private Map mModuleMap = new ConcurrentHashMap<>();
@Override
public boolean hasLoadModule(String tag) {
return mModuleLoadClassMap.containsKey(tag);
}
@Override
public BaseModule getModule(String tag) {//获取模块
if (TextUtils.isEmpty(tag)) {
return null;
}
return findModuleInMap(tag);
}
@Override
public boolean registerModule(String tag, Class> moduleImplCls) {//注册模块
if (TextUtils.isEmpty(tag) || moduleImplCls == null) {
return false;
}
mModuleLoadClassMap.put(tag, moduleImplCls);
return findModuleInMap(tag) != null;
}
private void preLoads() {
try {
for (Map.Entry entry : mModuleLoadClassMap.entrySet()) {
getModule(entry.getKey());
// loadModuleByTag(entry.getKey());
}
} catch (Exception e) {
}
}
private BaseModule loadModuleByTag(String tag) throws Exception {
return loadModuleByTag(tag, true);
}
/**
* gen
* @param tag
* @param preLoad
* @return
* @throws Exception
*/
private synchronized BaseModule loadModuleByTag(String tag, boolean preLoad) throws Exception {
Class clazz = mModuleLoadClassMap.get(tag);
if (clazz == null) {
throw new Exception("can not find impl class for tag:" + tag);
}
try {
BaseModule module = (BaseModule) clazz.newInstance();
mModuleMap.put(tag, module);
return module;
} catch (Throwable e) {
throw new Exception("can not load class:" + clazz.getName() + " for tag:" + tag);
}
}
private synchronized BaseModule findModuleInMap(String tag) {
BaseModule mod = mModuleMap.get(tag);
if (mod == null) {
try {
BaseModule module = loadModuleByTag(tag, false);
mod = module;
} catch (Exception t) {
mod = null;
}
}
return mod;
}
基类BaseModule
public abstract class BaseModule {
@Nullable
public static T getModule(String tag) {
BaseModule module = BaseContext.getInstance().getModule(tag);
if (module != null) {
return (T) module;
}
return null;
}
}
那我们怎么用呢?比如我们在Application的时候就加载这些模块提供出来的接口:
/**
* 加载模块
* @param application
*/
public void initializeModule(Application application) {
try {
BaseContext.baseOn(new ModleManager(),application);
IModuleManager moduleManager = BaseContext.getInstance().getModuleManager();
if(moduleManager!=null) {
moduleManager.registerModule(IAudioPlayerPlugin.TAG, IAudioPlayerPlugin.class);
moduleManager.registerModule(IModleAPlugin.TAG, IModleAPlugin.class);
moduleManager.registerModule(IModleBPlugin.TAG, IModleBPlugin.class);
moduleManager.registerModule(IModleFloatPlugin.TAG, IModleFloatPlugin.class);
}
} catch (Exception e) {
e.printStackTrace();
}
}
然后在activity中使用或者在其他模块中使用:
IModleAPlugin iModleAPlugin= BaseModule.getModule(IModleAPlugin.TAG);
iModleAPlugin.initModleA();
IModleBPlugin iModleBPlugin= BaseModule.getModule(IModleBPlugin.TAG);
iModleBPlugin.initModleB();
这样就做到的模块之间的解偶,开发人员可以只开发自己的模块不影响他人,代码简洁易维护。
demo参考:https://github.com/xxnan/ModlePlugin
更多文章请关注公众号: