java(Android)跨Module调用对应类方法需求解决方案

在开发组件化项目中,遇到一个这样的问题,两个不同的Module相互之间没有任何直接依赖关系,现在需求是需要在Module_A中调用Module_B中的某个类的方法,以下为解决此问题的方法;

采用的核心技术:路由、反射;

解决问题的过程,首先将需要调用的类通过路由注册,注册到路由中心,这里讲Module_B中的类注册到了路由中心,在Module_A中首先先通过路由中心获取到已经注册了的Module_B的类,获取到Class后通过反射原理获取当前对象实例,然后继续通过反射调用调用当前实例对象的对应方法(支持无参方法及有参方法),至此调用方法已实现,具体示例如下:

1、路由注册工具类:

/**
 * Class类路由注册工具类
 * Created by sun.li on 2018/7/6.
 *
 * @author sun.li
 */

public class RouterClassUtil implements RouterInter<Object,Class<? extends Object>>{

    private ConcurrentHashMap<String, Class<? extends Object>> mClassZ = new ConcurrentHashMap();
    private ConcurrentHashMap<String, Object> mClassA = new ConcurrentHashMap();
    private static RouterClassUtil mInstance;

    private RouterClassUtil() {
    }

    public static RouterClassUtil getInstance() {
        if(null == mInstance) {
            synchronized(RouterActivity.class) {
                if(null == mInstance) {
                    mInstance = new RouterClassUtil();
                }
            }
        }
        return mInstance;
    }

    @Override
    public void routerT(String key, Object obj) {
        Object cacheActivity = this.mClassA.get(key);
        if(null == cacheActivity || obj != cacheActivity) {
            this.mClassA.put(key, obj);
        }
    }

    @Override
    public Object invokT(String key) {
        return this.mClassA.get(key);
    }

    @Override
    public void routerV(String key, Class<?> aClass) {
        Class cacheClass = this.mClassZ.get(key);
        if(null == cacheClass || aClass != cacheClass) {
            this.mClassZ.put(key, aClass);
        }
    }

    @Override
    public Class<? extends Object> invokV(String key) {
        return this.mClassZ.get(key);
    }

    /** 获取Object对象*/
    public Object getObject(String key){
        Object object = invokT(key);
        if(null == object){
            try {
                Class<? extends Object> aClass = invokV(RouterHttpClassKey.KEY_MODULE_HTTP_HTTPUTIL);
                if(null != aClass) {
                    object = aClass.newInstance();//通过Class对象实例化当前对象
                }
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
        return object;
    }
}

2、路由对应Class配置类(此处声明具体的Class类路径,注册时通过反射原理获取对应的Class):

/**
 * 路由跳转Class对应key配置类
 * Created by sun.li on 2018/7/6.
 *
 * @author sun.li
 */

public class RouterHttpClassKey {

    /**
     * HttpUtil
     */
    public static final String KEY_MODULE_HTTP_HTTPUTIL = "**.**.**.util.HttpLibUtil";
}

3、路由注册:

RouterClassUtil.getInstance().routerV(value,correspondingClass);

4、路由调用获取当前的对象并且通过反射调用对应的方法:

4.1、无参方法调用:

/** 调用Module中的对应无参方法*/
public void callMethodInModule(@NonNull String className,@NonNull String methodName){
    Object object = RouterClassUtil.getInstance().getObject(className);
    if (null != object) {
        Method method = getMethod(object,methodName,null);
        if(null!=method){
            try {
                //执行对象object中通过反射获取的方法
                method.invoke(object);
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }
        }
    }
}

4.2、有参方法调用(发射调用多参数时因为方法限制,还未想到好的方式):

/**
 * 公共网络请求参数对象
 * Created by sun.li on 2018/7/6.
 *
 * @author sun.li
 */

public class BaseObjectParameterBean {

    public BaseObjectParameterBean(){

    }

    public BaseObjectParameterBean(Class parameterType, Object parameterValue){
        setParameterType(parameterType);
        setParameterValue(parameterValue);
    }

    /** 参数值*/
    private Object parameterValue;

    /** 参数类型*/
    private Class parameterType;

    public Object getParameterValue() {
        return parameterValue;
    }

    public void setParameterValue(Object parameterValue) {
        this.parameterValue = parameterValue;
    }

    public Class getParameterType() {
        return parameterType;
    }

    public void setParameterType(Class parameterType) {
        this.parameterType = parameterType;
    }
}

/** 调用Module中的对应有参方法*/
public void callMethodInModule(@NonNull String className, @NonNull String methodName, List<BaseObjectParameterBean> mList){
    if(null!=mList && mList.size()>0){
        /* 参数类型集合*/
        List<Class> classList = new ArrayList<>();
        /* 参数值集合*/
        List<Object> objectList = new ArrayList<>();
        for (int i = 0; i < mList.size(); i++) {
            BaseObjectParameterBean baseHttpRequestParameterBean = mList.get(i);
            if(null != baseHttpRequestParameterBean){
                if(null != baseHttpRequestParameterBean.getParameterValue() && null != baseHttpRequestParameterBean.getParameterType()){
                    classList.add(baseHttpRequestParameterBean.getParameterType());
                    objectList.add(baseHttpRequestParameterBean.getParameterValue());
                }
            }
        }
        if(classList.size()>0 && objectList.size()>0){
            Object object = RouterClassUtil.getInstance().getObject(className);
            if (null != object) {
                Method method = getMethod(object,methodName,classList);
                if(null!=method){
                    try {
                        //执行对象object中通过反射获取的方法
                        Object[] mObjectList = new Object[objectList.size()];
                        for (int i = 0; i < objectList.size(); i++) {
                            if(null != objectList.get(i)){
                                mObjectList[i] = objectList.get(i);
                            }
                        }
                        method.invoke(object,mObjectList);
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    } catch (InvocationTargetException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }else{
        callMethodInModule(className,methodName);
    }
}

private Method getMethod(Object object, @NonNull String methodName, List<Class> mList){
    if(null == object || TextUtils.isEmpty(methodName)){
        return null;
    }
    Method method = null;
    try {

        if(null != mList && mList.size()>0){
            // 父类对象调用子类有参数的方法(反射原理)
            Class[] mClassList = new Class[mList.size()];
            for (int i = 0; i < mList.size(); i++) {
                if(null != mList.get(i)){
                    mClassList[i] = mList.get(i);
                }
            }
            method = object.getClass().getMethod(methodName,mClassList);
        }else{
            method = object.getClass().getMethod(methodName);// 父类对象调用子类方法(反射原理)
        }
    } catch (NoSuchMethodException e) {
        e.printStackTrace();
    }
    return method;
}

4.3、调用示例:

BaseObjectUtil.getInstance().callMethodInModule(RouterHttpClassKey.KEY_MODULE_HTTP_HTTPUTIL,"test");

List<BaseHttpRequestParameterBean> beans = new ArrayList<>();
beans.add(new BaseHttpRequestParameterBean(String.class,"哈哈"));
beans.add(new BaseHttpRequestParameterBean(Integer.class,88));

BaseHttpRequestParameterBean baseHttpRequestParameterBean = new BaseHttpRequestParameterBean();
baseHttpRequestParameterBean.setParameterType(Integer.class);
beans.add(baseHttpRequestParameterBean);

BaseObjectUtil.getInstance().callMethodInModule(RouterHttpClassKey.KEY_MODULE_HTTP_HTTPUTIL,"test2",beans);

调用结果:

07-06 16:07:29.862 10329-10329/cc.**.** E/HttpLibUtil:: 我是HttpLib中的test方法
07-06 16:07:29.862 10329-10329/cc.**.** E/HttpLibUtil:: 我是HttpLib中的test2方法,str=哈哈 i=88 

猜你喜欢

转载自www.cnblogs.com/Free-Thinker/p/10304034.html