android多模块解偶

在项目中我们随着功能越做越多,工程会越来越大,随之而来的我们会将某一功能单独提取出来作为一个模块,但是我们有希望这个模块是独立的,不要和其他模块相互引用,每个模块的代码不要引入在其他模块。

为了解偶我们想到接口的方式,每个模块提供一套接口出来,其他模块需要用到这个功能可以通过接口来调用,达到解偶的目的。先看一下项目结构:

android多模块解偶_第1张图片

包含了modleA,modleB,basic,floatview等模块而除了basic之外其他模块里面都有一个interface工程,那么他们之间的引用关系是怎样的呢?

看一张图:

android多模块解偶_第2张图片

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

更多文章请关注公众号:

android多模块解偶_第3张图片

 

你可能感兴趣的:(android)