Android组件解耦万能接口

Android组件解耦万能接口

  • Fragment间通信原则
  • 如何降耦、解耦
  • 第三方如何设计
    • 如何保存一个方法
    • 如何定义方法的接口
    • 如何对所有的方法进行管理

Fragment间通信原则

引用Google官方的话来说,Two Fragments should never communicate directly.
即:Fragment间不应该直接通信。

如何降耦、解耦

既然组件间的通信不应该直接进行,那么就需要引入第三方来做一个信使。通信双方应彼此独立,互不依赖,需要对方什么,就直接去找第三方代为传达,相当于中介的存在。

第三方如何设计

第三方应掌握所有参与通信的对象的需要提供给外部的信息和接口,例如,FragmentOne有一个方法methodA(),需要提供给FragmentTwo来调用,那么FragmentOne就需要让第三方保存methodA(),当FragmentTwo需要调用methodA的时候,只需要向第三方发送调用请求。

如何保存一个方法

在Java中,可以很容易的将一个字段,一个对象传给第三方来保存,但没有一个直接的方式来保存一个方法的引用,那该如何去实现方法的保存呢

很显然,通过接口,将我们的方法封装到对象中去。

如何定义方法的接口

这里说的接口,不是说声明为interface的才叫接口,它也可以是一个抽象基类。
首先为所有的抽象基类定义一个公共基类,来保存方法的基本信息

Function.java

public class Function {

    private String functionName;

    public Function(String functionName) {
        this.functionName = functionName;
    }

    public String getFunctionName() {
        return functionName;
    }
}

这里我们只需要保存方法名即可,因为这里并不是要通过反射的方式去实现方法的调用。

一个方法,可以分为以下四种类型:
参数 返回值;
参数 返回值;
参数 返回值;
参数 返回值;

这里的参数,个数统一设置为1,对于需要多个参数的方法,可以通过封装一个对象来进行传参,和EventBus要求单个参数的原因一致,都是为了方便管理,统一规范

接下来就来实现这四种类型方法的抽象类:

FunctionNoParamNoResult.java

public abstract class FunctionNoParamNoResult extends Function {

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

    public abstract void invoke();
}

FunctionHasParamNoResult.java

public abstract class FunctionHasParamNoResult<T> extends Function {

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

    public abstract void invoke(T param);
}

FunctionNoParamHasResult.java

public abstract class FunctionNoParamHasResult<T> extends Function {

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

    public abstract T invoke();
}

FunctionHasParamHasResult.java

public abstract class FunctionHasParamHasResult<T, P> extends Function {

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

    public abstract T invoke(P param);
}

四个类都非常简单,只有invoke方法不同,而在组件中,只需将要保存的方法在invoke中进行实现即可。

如何对所有的方法进行管理

所有的方法类都实现了,那么如何对他们进行管理呢?很简单,使用四个Map就可以了。

在管理类中,只需要为每一种类型的方法分别提供两个接口:添加方法和调用方法

当然,第三方管理类需要做成单例,并保存四种方法类型的Map:

FunctionManager.java

private static volatile FunctionManager sInstance;

private Map<String, FunctionNoParamNoResult> mNoParamNoResultMap;
private Map<String, FunctionNoParamHasResult> mNoParamHasResultMap;
private Map<String, FunctionHasParamNoResult> mHasParamNoResultMap;
private Map<String, FunctionHasParamHasResult> mHasParamHasResultMap;

public static FunctionManager getInstance(){
   if(sInstance == null){
        synchronized (FunctionManager.class){
            if(sInstance == null) {
                sInstance = new FunctionManager();
            }
        }
    }
    return sInstance;
}

private FunctionManager() {
 	mNoParamNoResultMap = new HashMap<>();
    mNoParamHasResultMap = new HashMap<>();
    mHasParamNoResultMap = new HashMap<>();
    mHasParamHasResultMap = new HashMap<>();
}

为无参数无返回值的方法提供添加和调用:

public void addFunction(FunctionNoParamNoResult function){
   mNoParamNoResultMap.put(function.getFunctionName(), function);
}

public void invokeFunction(String functionName){
    if(TextUtils.isEmpty(functionName)){
        return;
    }
    if(mNoParamNoResultMap != null){
        FunctionNoParamNoResult f = mNoParamNoResultMap.get(functionName);
        if(f != null){
            f.invoke();
        } else {
            new FunctionNotFoundException("has no this invoke " + 
                    functionName).printStackTrace();
        }
    }
}

为无参数有返回值的方法提供添加和调用:

public void addFunction(FunctionNoParamHasResult function){
   mNoParamHasResultMap.put(function.getFunctionName(), function);
}

public <T> T invokeFunction(String functionName, Class<T> t){
   if(TextUtils.isEmpty(functionName)){
       return null;
   }
   if(mNoParamHasResultMap != null){
       FunctionNoParamHasResult f = mNoParamHasResultMap.get(functionName);
       if(f != null){
           return t.cast(f.invoke());
       } else {
           new FunctionNotFoundException("has no this invoke " + 
                   functionName).printStackTrace();
       }
   }
   return null;
}

为有参数无返回值的方法提供添加和调用:

public void addFunction(FunctionHasParamNoResult function){
    mHasParamNoResultMap.put(function.getFunctionName(), function);
}

public <P> void invokeFunction(String functionName, P p){
    if(TextUtils.isEmpty(functionName)){
        return;
    }
    if(mHasParamNoResultMap != null){
        FunctionHasParamNoResult f = mHasParamNoResultMap.get(functionName);
        if(f != null){
            f.invoke(p);
        } else {
            new FunctionNotFoundException("has no this invoke " + 
                    functionName).printStackTrace();
        }
    }
}

为有参数有返回值的方法提供添加和调用:

public void addFunction(FunctionHasParamHasResult function){
   mHasParamHasResultMap.put(function.getFunctionName(), function);
}

public <T,P> T invokeFunction(String functionName, P p, Class<T> t) {
   if(TextUtils.isEmpty(functionName)){
       return null;
   }
   if(mHasParamHasResultMap != null){
       FunctionHasParamHasResult f = mHasParamHasResultMap.get(functionName);
       if(f != null) {
           if(t != null){
               return t.cast(f.invoke(p));
           }
       }
   }
   return null;
}

FunctionNotFoundException.java

public class FunctionNotFoundException extends Exception {

    public FunctionNotFoundException(String message) {
        super(message);
    }
}

到此就完成了所有的封装工作,每一个类都非常的简单,也很容易理解。

调用也很简单:

添加方法

FunctionManager.getInstance().addFunction(
       new FunctionHasParamNoResult<String>("hasParamNoResult") {
   @Override
   public void invoke(String param) {
       //do something
   }
});

调用方法

FunctionManager.getInstance().invokeFunction("hasParamNoResult", "Hello from the FragmentOne");

从头到尾,都只是使用了非常基础的Java知识,没有调用生疏的方法、也没有晦涩的知识点。

当然,这样的封装只是为了表达解耦的思想,如果真要在项目中使用,那还是直接去用已经封装得非常好且功能更全面、性能也更好的第三方插件就好了。在开发中,解耦是个非常重要的问题,项目越大,解耦带来的便利性越明显;相反,如果模块间耦合度太高,就会出现牵一发而动全身的问题,稍微改一个地方就可能让整个项目都无法正常运行。

很多时候,并不是技术水平阻碍了自己,而是我的视角,高度,让我连这么简单的方案可能都想不到。当然,经验可能会是很重要的原因,但我相信,一定还有其他的办法来提高自己的视野,格局,而不单是仅仅靠工作经验。

你可能感兴趣的:(Android)