LZ-Says:我觉得,干什么,都需要一个奔头,有了奔头,看到了希望,路再难,又有何妨?
前言
今天,为大家带来的是如何打造万能的Interface?
那么有的小伙伴就会问了,为啥要打造,我用的挺好的啊。
别急,下面为大家引入。
下面我们先看下本文最终效果:
分析
现如今,大多数的App开发都是基于一个主要的Activity,其次,通过和Fragment配合,从而实现产品脑洞大开的想法。当然,这里有的小伙伴就说了,我开发app就不是这么玩的,基于BaseActivity,各种Activity,照样不是玩的挺好的嘛?
那么这里你要考虑一个问题,Fragment出现的原因是什么?
首先为大家简述下Fragment小历史。
Fragment,在Android 2.3版本后出现,出现的主要目的就是解决Android碎片化太过严重的问题,当然,这里也会有其他的一些原因,这里不做过多说明。
那么,Fragment和Activity之间有什么区别呢?
首先,大家知道的,Fragment存在于Activity中,Activity销毁,随即Fragment同时销毁,想必之下,多个Activity势必会增加App占用的系统资源,所以,我们为何不去让我们的App更加优良?
下面简单绘制下,基于一个MainActivity以及配合n个Fragment的简图:
基于以上无比丑陋的图,我们可以清晰的看到,假设我们的App按照如上方式进行实现,那么他们之前的通信方式或者说是通信的流程又是如何的呢?
老规矩,放一张简图:
每个相同箭头颜色值都代表当前MainActivity与不同的Fragment之间的交互,不知道大家有没有发现,Activity和Fragment之间的耦合度很高,那么如何减少俩者间的耦合度呢?
我们的万能Interface就上场了。
这时候,有的伙伴就说了,我直接在某些情况下,让Fragment与Fragment直接进行交互不久好了嘛。当然,没有问题,But,这里为大家普及下:
Fragment之间通信原则: Two Fragments should never communicate diretly.
俩个Fragment之间不能进行直接通信 这样会造成fragment之间耦合度很高。也就是说谷歌并不建议我们这么做。
有的人就说了,不建议归不建议,我就这么玩。没事,跳楼玩都可以~
通信 交互
一般来说,我们的Fragment与Activity交互如上图所示,形成的一个流程图如下:
Fragment1 —> Activity —> Fragment2
那么我们平时是如何进行Fragment之间通信呢?这里为大家列举如下几种:
使用EventBus;
使用老伙计Handler;
使用Static变量;
使用广播;
使用接口
那么这里,我们分别对如上几点进行简单分析,对比下优劣势。
1. EventBus
优点:使用方便,快捷
缺点:
1.大家知道EventBus内部通过反射进行操作,而反射在Android中则会对性能有部分的损耗。而我们的App中,UI显示的速度以及相应时间则尤为重要,可能短暂的延迟和卡顿就会降低用户使用体验度;
2.后期代码维护相对比较困难,想当初学习的时候,各种蒙比,有时候甚至找不到传递的值在哪儿接收;
3.而最重要的一点则是,EventBus是单向传递数据,通俗来讲就是不能返回数据,这边就比较恶心了。
2. Handler
优点:能解决问题
缺点:
1.与其配合使用统一反应出的问题就是耦合度太高;
2.无法获取activity的返回结果。比如Fragment发送一个数据到Activity中 要求Activity处理完之后返回到Fragment中,那么这时候Handler有点low了;
3.内存泄漏
3. Static
缺点:用static修改的变量等一般都是存在于内存中,当多个变量存在的时候,便会加大系统内存,无形中也在消耗系统资源
4. 广播
首先要明确,虽然我们玩广播几行代码的事儿,但是我们要知道,广播机制以及内部实现是一个非常庞大且非常复杂的系统应用,同时,也一般被应用于监听系统为主,例如开机,接收短信等等
缺点如下:
1.性能差 有延迟;
2.传播的数据有限;
3.代码冗余,而且一个广播发出,会在多个地方被接受到,无形中消耗资源
5. 接口
优点:
优点 简单 效率高 方便 解耦合
缺点:
代码冗余 每个通信的fragment 都必须定义自己独一无二的接口
深入分析 细化
首先查看下,之前接口实现方式:
public interface OnClickListener {
void onClick(View var1);
}
LZ对此画个一个简图,凑合看看:
基于以上简图,首先明白以下几点:
每个接口都拥有接口名称;
接口方法拥有四种状态,具体如图所示。
接下来开始我们抽取行动~
撸码
定义FunctionManger管理类,主要用来管理我们封装提取的接口方法。
一、提取方法名
public static abstract class Function {
public String mFunctionName;
public Function(String functionName) {
this.mFunctionName = functionName;
}
}
二、提取方法
/**
* 无参数 无返回
*/
public static abstract class FunctionWithNothing extends Function {
public FunctionWithNothing(String functionName) {
super(functionName);
}
public abstract void function();
}
/**
* 有参数 无返回
*
* @param <Param>
*/
public static abstract class FunctionWithParam<Param> extends Function {
public FunctionWithParam(String functionName) {
super(functionName);
}
public abstract void function(Param param);
}
/**
* 有返回 无参数
*
* @param <Result>
*/
public static abstract class FunctionWithResult<Result> extends Function {
public FunctionWithResult(String functionName) {
super(functionName);
}
public abstract Result function();
}
/**
* 有参数 有返回
*/
public static abstract class FunctionWithHaving<Result, Param> extends Function {
public FunctionWithHaving(String functionName) {
super(functionName);
}
public abstract Result function(Param data);
}
三、自定义错误异常类 主要拦截null
public class FunctionException extends Exception {
public FunctionException(String errorMsg) {
super(errorMsg);
}
}
四、创建实体类 用于传输数据 参数
public class FunctionParams {
private Bundle mParams = new Bundle(1);
private int mIndex = -1;
private Map mObjectParams = new HashMap(1);
public FunctionParams(Bundle mParams, Map mObjectParams) {
this.mParams = mParams;
this.mObjectParams = mObjectParams;
}
public <Param> Param getObject(Class<Param> p) {
if (mObjectParams == null) {
return null;
}
return p.cast(mObjectParams.get((mIndex++) + ""));
}
/**
* 获取int值
*
* @return
*/
public int getInt() {
if (mParams != null) {
return mParams.getInt((mIndex++) + "");
}
return 0;
}
/**
* 获取int值
*
* @param defalut
* @return
*/
public int getInt(int defalut) {
if (mParams != null) {
return mParams.getInt((mIndex++) + "");
}
return defalut;
}
/**
* 获取字符串
*
* @param defalut
* @return
*/
public String getString(String defalut) {
if (mParams != null) {
return mParams.getString((mIndex++) + "");
}
return defalut;
}
/**
* 获取字符串
*
* @return
*/
public String getString() {
if (mParams != null) {
return mParams.getString((mIndex++) + "");
}
return null;
}
/**
* 获取Boolean值
*
* @return 默认返回false
*/
public boolean getBoolean() {
if (mParams != null) {
return mParams.getBoolean((mIndex++) + "");
}
return false;
}
}
五、封装参数拼接管理类
public class FunctionParamsBuilder {
private Bundle mParams;
private int mIndex = -1;
private Map mObjectParams = new HashMap(1);
public FunctionParamsBuilder() {
}
public FunctionParams create() {
FunctionParams instance = new FunctionParams(mParams, mObjectParams);
return instance;
}
public FunctionParamsBuilder putInt(int value) {
if (mParams == null) {
mParams = new Bundle(2);
}
mParams.putInt((mIndex++) + "", value);
return this;
}
public FunctionParamsBuilder putString(String value) {
if (mParams == null) {
mParams = new Bundle(2);
}
mParams.putString((mIndex++) + "", value);
return this;
}
public FunctionParamsBuilder putBoolean(boolean value) {
if (mParams == null) {
mParams = new Bundle(2);
}
mParams.putBoolean((mIndex++) + "", value);
return this;
}
public FunctionParamsBuilder putObject(Object value) {
if (mObjectParams == null) {
mObjectParams = new HashMap(1);
}
mObjectParams.put((mIndex++) + "", value);
return this;
}
}
六、封装接口名
/**
* 定义接口
*/
public static final String INTERFACE = BlankFragment1.class.getName() + "NPNR";
public static final String INTERFACE_HAVE_RESULT = BlankFragment1.class.getName() + "NPYR";
public static final String INTERFACE_HAVE_PARAM = BlankFragment1.class.getName() + "YPNR";
public static final String INTERFACE_HAVE_PARAM_RESULT = BlankFragment1.class.getName() + "YPYR";
public static final String INTERFACE_HAVE_MORE_PARAM = BlankFragment1.class.getName() + "MP";
public static final String INTERFACE_HAVE_MORE_PARAM_NO_RESULT = BlankFragment1.class.getName() + "MPNR";
public static final String INTERFACE_HAVE_MORE_PARAM_RESULT = BlankFragment1.class.getName() + "MPNRYP";
七、提取回调函数
/**
* 根据函数名 回调无返回值无参数
*
* @param functionName
*/
public void invokeFunction(String functionName) {
FunctionWithNothing functionWithNothing = null;
if (mFunctionWithNothing != null) {
functionWithNothing = mFunctionWithNothing.get(functionName);
if (functionWithNothing != null) {
functionWithNothing.function();
}
}
if (functionWithNothing == null) {
try {
throw new FunctionException("没有此函数:" + functionName);
} catch (FunctionException e) {
e.printStackTrace();
}
}
}
/**
* 根据函数名 回调有返回值无参数
*
* @param functionName
* @param resultClass
* @param <Result>
* @return
* @throws FunctionException
*/
public <Result> Result invokeFunctionWithResult(String functionName, Class<Result> resultClass) {
FunctionWithResult functionWithResult = null;
if (mFunctionWithResult != null) {
functionWithResult = mFunctionWithResult.get(functionName);
if (functionWithResult != null) {
if (resultClass != null) {
return resultClass.cast(functionWithResult.function());
} else {
return (Result) functionWithResult.function();
}
}
}
if (functionWithResult == null) {
try {
throw new FunctionException("没有此函数");
} catch (FunctionException e) {
e.printStackTrace();
}
}
return null;
}
/**
* 回调有参数 无返回函数
*
* @param functionName
* @param param
* @param <Param>
*/
public <Param> void invokeFunction(String functionName, Param param) {
FunctionWithParam functionWithParam = null;
if (mFunctionWithParam != null) {
functionWithParam = mFunctionWithParam.get(functionName);
if (functionWithParam != null) {
functionWithParam.function(param);
}
}
}
/**
* 调用具有参数,同时具有返回值的函数
*
* @param funcName
* @param param
* @param <Result>
* @param <Param>
* @return
*/
public <Result, Param> Result invokeFuncWithResult(String funcName, Param param, Class<Result> c) {
FunctionWithHaving functionWithHaving = null;
if (mFunctionWithHaving != null) {
functionWithHaving = mFunctionWithHaving.get(funcName);
if (functionWithHaving != null) {
if (c != null) {
return c.cast(functionWithHaving.function(param));
} else {
return (Result) functionWithHaving.function(param);
}
}
}
if (functionWithHaving == null) {
try {
throw new FunctionException("没有此函数");
} catch (FunctionException e) {
e.printStackTrace();
}
}
return null;
}
/**
* 添加无参数 无返回
*
* @param functionWithNothing
* @return
*/
public FunctionManger addFunction(FunctionWithNothing functionWithNothing) {
if (functionWithNothing == null) {
return this;
}
if (mFunctionWithNothing == null) {
mFunctionWithNothing = new HashMap<>(1);
}
mFunctionWithNothing.put(functionWithNothing.mFunctionName, functionWithNothing);
return this;
}
/**
* 添加有返回
*
* @param functionWithResult
* @return
*/
public FunctionManger addFunction(FunctionWithResult functionWithResult) {
if (functionWithResult == null) {
return this;
}
if (mFunctionWithResult == null) {
mFunctionWithResult = new HashMap<>(1);
}
mFunctionWithResult.put(functionWithResult.mFunctionName, functionWithResult);
return this;
}
/**
* 添加有参数无返回值
*
* @param function
* @return
*/
public FunctionManger addFunction(FunctionWithParam function) {
if (function == null) {
return this;
}
if (mFunctionWithParam == null) {
mFunctionWithParam = new HashMap<>(1);
}
mFunctionWithParam.put(function.mFunctionName, function);
return this;
}
/**
* 添加既有参数又有返回值
*
* @param function
* @return
*/
public FunctionManger addFunction(FunctionWithHaving function) {
if (function == null) {
return this;
}
if (mFunctionWithHaving == null) {
mFunctionWithHaving = new HashMap<>(1);
}
mFunctionWithHaving.put(function.mFunctionName, function);
return this;
}
八、BaseFragment封装
public class BaseFragment extends Fragment {
protected BaseActivity mBaseActivity;
protected FunctionManger mFunctionManger;
public void setFunctionManger(FunctionManger functionManger) {
this.mFunctionManger = functionManger;
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof MainActivity) {
mBaseActivity = (BaseActivity) context;
mBaseActivity.setFunctionForFragment(getId());
}
}
}
九、实际调用
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
mFunctionManger.invokeFunction(INTERFACE);
}
});
btn2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
mFunctionManger.invokeFunction(INTERFACE_HAVE_RESULT);
String result = mFunctionManger.invokeFunctionWithResult(INTERFACE_HAVE_RESULT, String.class);
btn2.setText(result);
}
});
btn3.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
mFunctionManger.invokeFunction(INTERFACE_HAVE_PARAM, 100);
}
});
btn4.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
List<String> strList = mFunctionManger.invokeFuncWithResult(INTERFACE_HAVE_PARAM_RESULT, 100, List.class);
if (strList != null) {
String st = "";
for (int i = 0; i < strList.size(); i++) {
st += strList.get(i) + " ";
}
btn4.setText(st);
}
}
});
btn5.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
mFunctionManger.invokeFunction(INTERFACE_HAVE_MORE_PARAM,
new FunctionParamsBuilder().putString("你好")
.putString("我是fragment").putInt(200).create());
}
});
btn6.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Bundle bundle = new Bundle();
bundle.putString("p", "你好activity");
bundle.putString("p1", "我是fragment");
bundle.putInt("p2", 200);
mFunctionManger.invokeFunction(INTERFACE_HAVE_MORE_PARAM_NO_RESULT, bundle);
}
});
btn7.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Bundle bundle = new Bundle();
bundle.putString("p", "你好activity2");
bundle.putString("p1", "我是fragment2");
bundle.putInt("p2", 300);
List<String> strList = mFunctionManger.invokeFuncWithResult(INTERFACE_HAVE_MORE_PARAM_RESULT, bundle, List.class);
btn7.setText("接收返回个数:" + strList.size() + " Result1:" + strList.get(0).toString() + " Result2:" + strList.get(1).toString() + " Result3:" + strList.get(2).toString());
}
});
}