UI组件通信框架

我们最常常遇到的UI组件通信有,activity和activity,activity和fragment。方法很多,开源的项目也有,如rxbus,eventbus,这些框架多多少少都有缺点,如不支持返回值。使用event还使得代码及其难维护。

现在自己手写实现一个UI组件通信框架,支持参数,返回值。

该框架的主要思想是对接口进行面向对象,进行抽象。

我们知道,一个接口中的方法,一定有方法名。至于参数和返回值,或可有可无,根据业务而定。

因此我们对其定义一个基本的抽象

/**
 * 对接口的抽象
 */
public static abstract class Function
{
   private String mFunctionName;

   public String getFunctionName()
   {
      return mFunctionName;
   }

   private Function(String functionName)
   {
      mFunctionName = functionName;
   }
}
至于方法体的样式,就是四类了。

1,无参无返回值的

/**
 * no params no result
 */
public static abstract class FunctionNPNR extends Function {

    public FunctionNPNR(String functionName) {
        super(functionName);
    }

    public abstract void onInvoke(Bundle data);
}

2,无参有返回值的

/**
 * no params with result
 *
 * @param <Result>
 */
public static abstract class FunctionNPWR<Result> extends Function {

    public FunctionNPWR(String functionName) {
        super(functionName);
    }

    public abstract Result onInvoke(Bundle data);
}
3,有参无返回值的


/**
 * no result with params
 */
public static abstract class FunctionNRWP extends Function {

    public FunctionNRWP(String functionName) {
        super(functionName);
    }

    public abstract void onInvoke(Map, String> params, Bundle data);
}

4,有参有返回值的

/**
 * with result with params
 */
public static abstract class FunctionWRWP<Result> extends Function {

    public FunctionWRWP(String functionName) {
        super(functionName);
    }

    public abstract Result onInvoke(Map, String> params, Bundle data);
}

对外暴露注册的api

/**
 * regist function in place where your busness need
 *
 * @param f
 */
public void registFunc(Function f)
{
   mFunctionHashMap.put(f.getFunctionName(), f);
}

对外暴露调用的api

    /**
     * trigger the function you have registed in everywhere you want
     *
     * @param funcName, 函数名
     * @param clazz,    触发后的返回值类型字节码
     * @param params    ,触发参数
     * @param data      ,给注册者的数据
     * @param <T>       
     * @return
     */
    public <T> T invokeFunc(String funcName, Class<T> clazz, Map, String> params, Bundle data) {
        Function function = mFunctionHashMap.get(funcName);
        if (function == null) {
            return null;
//            throw new IllegalArgumentException("no such function:" + funcName + ",have you regist " + "this function somewhere first?");
        }

        data = data == null ? new Bundle() : data;
        if (clazz != null) {
            //1 no params with result
            if (params == null) {
                if (function instanceof FunctionNPWR) {
                    return clazz.cast(((FunctionNPWR) function).onInvoke(data));
                } else {
                    return throwException(function, FunctionNPWR.class);
                }
            } else {
                //2 with params with result
                if (function instanceof FunctionWRWP) {
                    return clazz.cast(((FunctionWRWP) function).onInvoke(params, data));
                } else {
                    return throwException(function, FunctionWRWP.class);
                }

            }
        } else {
            //1 no params no result
            if (params == null) {
                if (function instanceof FunctionNPNR) {
                    ((FunctionNPNR) function).onInvoke(data);
                } else {
                    return throwException(function, FunctionNPNR.class);
                }
            } else {
                //2 with params no result
                ((FunctionNRWP) function).onInvoke(params, data);
            }
        }
        return null;
    }
 
  

/**
 * 当调用参数不匹配时,抛出异常
 * @param function
 * @param functionClazz
 * @param <T>
 * @return
 */
private <T> T throwException(Function function, Classextends Function> functionClazz)
{
   throw new ClassCastException("the function " + function.getFunctionName() + " when regist is not " + "match:" + functionClazz);
}


最后将上面的类或者方法放入一个单例类中

public class Functions
{
   private static HashMap, Function> mFunctionHashMap = new HashMap<>();

   private Functions()
   {
   }

   public static Functions getInstance()
   {
      return mSingleton.get();
   }

   private static Singleton mSingleton = new Singleton()
   {
      @Override
      protected Functions create()
      {
         return new Functions();
      }
   };}

框架就完成了。

接下来进行使用。

业务场景如下,页面的titlebar隶属于activity,该activity中间容器包含的是fragment,点击titlebar的刷新控件,fragment进行刷新。刷新“今天”的。

在fragment中进行注册:

Functions.getInstance().registFunc(new Functions.FunctionNPNR("orderList") {
    @Override
    public void onInvoke(Bundle data) {
        Toast.makeText(Main2Activity.this, "" + data.get("date"), Toast.LENGTH_SHORT).show();
    }
});

在activity中进行调用:

 
  
findViewById(R.id.tv).setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {

        //no param no result,告诉注册组件找出今天的订单
        Bundle bundle = new Bundle();
        bundle.putString("date", "今天");
        Functions.getInstance().invokeFunc("orderList", null, null, bundle);

    }
});

这是一个最简单的无参无返回值的调用场景,因此invokeFunc后面的返回值类型以及参数均无需指定,设为null即可。

如果需要有参有返回值,注册时则选用FunctionWRWP,其他以此类推,根据业务需求选择对应的function类型。






你可能感兴趣的:(架构)