Activity与Fragment通信 多接口实现优化

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;
    }
}


BaseFragment 和 MainFragment

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();
                }
            }
        });

    }
}

MainActivity

其中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%)完美解决方案


其实个人觉得也没有特别完美,使用接口的方式,代码会更直观。


你可能感兴趣的:(Android,Activity通信)