Android Study之打造万能Interface

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

GitHub查看地址

https://github.com/HLQ-Struggle/NiceInterface

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

HLQ_Struggle

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值