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

2019-06-13 10:09:51

参考地址  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



  • 2018-11-26 17:03:59

    有些 where 条件会导致索引无效

    在查询中,WHERE 条件也是一个比较重要的因素,尽量少并且是合理的 where 条件是徆重要的,尽量在多个条件的时候,把会提取尽量少数据量的条件放在前 面,减少后一个 where 条件的查询时间。

  • 2018-11-26 17:05:47

    sql查询调优之where条件排序字段以及limit使用索引的奥秘

    看起来匪夷所思,其实搞清楚mysql查询的原理之后,其实很简单 我们来看这2条sql查询,都用到了where order by limit 当有limit存在时,查询的顺序就有可能发生变化,这时并不是从数据库中先通过where过滤再排序再limit 因为如果这样的话,从500万数据中通过where过滤就不会是5s了。

  • 2018-11-26 21:46:28

    TextView设置行间距、行高,以及字间距

    Android系统中TextView有默认行间距,但是比较窄有的时候需要我们设置每行行间距。 TextView为我们提供了相关设置属性android:lineSpacingExtra或android:lineSpacingMultiplier。

  • 2018-11-26 21:47:55

    Drawable一个有趣的属性:tileMode

    tileMode是drawable 资源文件 bitmap的一个属性, 翻译的意思是平铺模式。用法如下: 在drawable目录下新建一个资源文件 tile_mode_demo.xml

  • 2018-11-28 09:55:53

    android radiogroup样式(设置切换背景与文字颜色)

    RadioButton(单选按钮)在Android开发中应用的非常广泛,比如一些选择项的时候,会用到单选按钮。它是一种单选框双状态的按钮,可以选择或不选择。在RadioButton没有被选中时,用户能够按下或点击来选中它。

  • 2018-12-01 00:27:12

    批量kill mysql processlist进程

    如果大批量的操作能够通过一系列的select语句产生,那么理论上就能对这些结果批量处理。 但是mysql并没用提供eval这样的对结果集进行分析操作的功能。所以只能现将select结果保存到临时文件中,然后再执行临时文件中的指令。