1.问题
我们都知道Activity与Fragment通信的几种方式,推崇的应该是谷歌给出的接口方案。
地址:https://developer.android.com/training/basics/fragments/communicating.html#DefineInterface
当一个Activity与多个Fragment通信时,可能要定义多个接口,下面这种思想是减少接口的定义,可以编写出一套统一的代码。
2.思想
对方法对象的封装,key作为方法名字,value作为方法对象
使用效果和接口差不多
3.主要代码
方法的封装类
/**
* key为Fragment的标示
* value为回调函数
*/
public class Functions{
private HashMap mFunctionWithParamAndResults ;
public static class Function{
String functionName;
public Function(String functionName){
this.functionName = functionName;
}
}
/**带有参数和返回值的抽象方法的类*/
public static abstract class FunctionWithParamAndResult extends Function{
public FunctionWithParamAndResult(String functionName) {
super(functionName);
}
public abstract Result function(Param param);
}
/**添加带参数的函数*/
public Functions addFunction(FunctionWithParamAndResult function){
if(function == null){
return this;
}
if(mFunctionWithParamAndResults == null){
mFunctionWithParamAndResults = new HashMap<>();
}
mFunctionWithParamAndResults.put(function.functionName,function);
return this;
}
/** 调用具有参数的函数*/
public Result invokeFunction(String funcName, Class classofR,
Param param)throws NoFunctionException {
FunctionWithParamAndResult func = null;
if(mFunctionWithParamAndResults != null){
func = mFunctionWithParamAndResults.get(funcName);
if(func != null){
if(classofR != null){
return classofR.cast(func.function(param));//安全的
}
return (Result)func.function(param);
} else {
throw new NoFunctionException("has no Function:" + funcName
+ "found in FunctionWithParamAndResult");
}
}
return null;
}
}
MainFragment中定义static FUNC_WPAR可以对应理解为接口回调方式中接口的定义
mFunctions.invokeFunction 是调用抽象方法
public class BaseFragment extends Fragment{
protected Functions mFunctions;
protected BaseActivity mBaseActivity;
/**
* activity调用此方法进行设置Functions
* @param functions
*/
public void setFunctions(Functions functions){
this.mFunctions = functions;
}
@Override
public void onAttach(Context context) {
super.onAttach(context);
if(context instanceof BaseActivity){
mBaseActivity = (BaseActivity)context;
mBaseActivity.setFunctionsForFragment(getTag());
}
}
}
public class MainFragment extends BaseFragment {
public static final String FUNCTION_WPAR = "MAIN_FUNCTION_WITH_PARAM_AND_RESULT";
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_main, null);
return view;
}
@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
Button btn1 = (Button) view.findViewById(R.id.button1);
final TextView tv1 = (TextView) view.findViewById(R.id.textview1);
btn1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
try {
String result = mFunctions.invokeFunction(FUNCTION_WPAR,
String.class, "来自MainFragment参数");
tv1.setText(result);
} catch (NoFunctionException e) {
e.printStackTrace();
}
}
});
}
}
其中new Functions.FunctionWithParamAndResult相当于接口方式里的实现接口
public class MainActivity extends BaseActivity {
private Functions mFunctions = new Functions();
private FragmentManager mFragmentManager;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@Override
public void setFunctionsForFragment(String fragmentTAG) {
mFragmentManager = getSupportFragmentManager();
if("fragment_main".equals(fragmentTAG)){
BaseFragment mainFragment = (BaseFragment)mFragmentManager.findFragmentByTag(fragmentTAG);
mainFragment.setFunctions(mFunctions);
mFunctions.addFunction(new Functions.FunctionWithParamAndResult(MainFragment.FUNCTION_WPAR) {
@Override
public String function(String str) {
Toast.makeText(MainActivity.this,
"收到MainFragment参数:" + str,
Toast.LENGTH_SHORT).show();
return "Activty处理参数:" + str;
}
});
} else if("fragment_second".equals(fragmentTAG)){
BaseFragment secondFragment = (BaseFragment)mFragmentManager.findFragmentByTag(fragmentTAG);
secondFragment.setFunctions(mFunctions);
mFunctions.addFunction(new Functions.FunctionWithParamAndResult(SecondFragment.FUNCTION_WPAR) {
@Override
public String function(String str) {
Toast.makeText(MainActivity.this,
"收到SecondFragment参数:" + str,
Toast.LENGTH_SHORT).show();
return "Activty处理参数:" + str;
}
});
}
}
}
如果使用这种方式来代替接口实现Activity与Fragment的通信,会使代码的阅读性变差,假如一个Fragment中有两个参数和返回类型相同,但是名字不同的方法,需要定义两个方法名字,阅读代码的时候,你就需要频繁查看调用处对应的方法名。
代码地址
参考文章:
Android:Activity与Fragment通信(99%)完美解决方案
其实个人觉得也没有特别完美,使用接口的方式,代码会更直观。