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 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM