基于Retrofit扩展一个统一处理网络请求的CallBack

思路

首先我们来思考几个场景:

  • 场景一、 每次网络请求,都不能保证成功,如果你现在正在请求一段数据是为了加载一段网络列表,你在加载成功那里,把显示“正在加载”字样的View控件隐藏掉,那么如果请求失败,你是否还要再写一遍??
  • 场景二、 在APP请求网络过程中,难免遇到网络异常的情况,如果请求失败,就给用户一个比较友好的提示,比如 ‘网络开小差啦~’ 之类的提示。那么你是否每次请求都去写一遍 ‘网络开小差~’之类的提示语呢??
  • 场景三、 有时候用户的手机网络卡,当他打开一个页面发现数据很久都没有刷新出来,等的不耐烦就关闭了界面,当他关闭界面之后网络突然好了,这时候如果还按照你设定的流程走,会不会出现难以预料的问题呢?
  • 场景四、 你现在在做一个有登录功能的APP,这时你的后台人员跑过来跟你说,后台返回来的数据中,某一个字段如果为一个特定的值,你就去自动打开某个页面(譬如:当isLogin=false的时候,要你去自动打开登录页面。当isBank=true的时候,需要自动打开银行卡页面。等等……)。那么你是会怎么去处理这些看似 “变态” 实际却很常用的需求呢?

以上场景是我们在APP开发中经常遇到的情况,那么我们接下来的代码,就是要解决这样的需求,我们要用最少的代码来完成最绕的需求。

代码篇

  • 1 : 由于篇章关系,这里不会贴出全部代码,但是会贴出主要关键代码,完整代码将在文章结尾贴出。
  • 2 : 本篇章适用于已经熟悉了Retrofit的基本使用的人,所以如果对Retrofit都不会的话,建议先去熟悉一下Retrofit的基本使用。

解决场景一的需求:

我们当然不会每个成功或者失败的回调都去写一遍对“加载中”字样的控件的操作,这里封装了一个onFinally()方法,不管是网络请求成功,还是网络请求失败,都会去调用一次onFinally 所以,我们可以把对控件的统一操作事件写在onFinally里面(譬如:将下拉刷新控件的加载中的状态,修改为加载完成的状态)

Net net = retrofitBase.getRetrofit().create(Net.class);
Call<DataBean> call = net.getIndex(city);
call.enqueue(new SCallBack<DataBean>(this)
{
    @Override
    public void onSuccess(@NonNull DataBean result) throws Exception
    {
        Log.d("MainActivity", "onSuccess:"+result.getLat());
    }
    
    @Override
    public void onCache(@NonNull DataBean result) throws Exception
    {
        Log.d("MainActivity", "onCache");
    }
    
    @Override
    public void onFail(Throwable t)
    {
        super.onFail(t);
        Log.d("MainActivity", "onFail:");
    }
    
    @Override
    public void onFinally()
    {
        Log.d("MainActivity", "onFinally");
    }
});
  • 1 : 使用SICallBack,或者SCallBack 来替换Retrofit的CallBack,SCallBack 实现于SICallBack。
  • 2 : 传入上下文,支持传入的类型是:Context Fragment v4.app.Fragment
  • 3 : 重写onFinally()方法 。

解决场景二的需求:

对于这种统一的网络出错提示,这里提供了一个统一处理方式。

import android.content.Context;
import android.widget.Toast;

import com.xiaolei.exretrofitcallback.network.common.IFailEvent;
import com.xiaolei.exretrofitcallback.network.common.SICallBack;
/**
 * Created by xiaolei on 2017/12/15.
 */
public class MyFailEvent implements IFailEvent
{
    @Override
    public void onFail(SICallBack callBack, Throwable t, Context context)
    {
        Toast.makeText(context, "哇哦~,您的网络有问题哦~", Toast.LENGTH_SHORT).show();
    }
}
  • 1 : 新建一个类,实现IFailEvent接口。
  • 2 : 重写onFail方法。
  • 3 : 把类设置到Config里面去:Config.setFailedEventClass(MyFailEvent.class);

有人可能会说,你都定义封装好了,那如果我这个接口比较特殊,不想用这种统一的处理方式呢??
这种情况的确存在,所以,如果您在某个接口不想使用统一的错误处理方式。那么在调用SICallBack的时候,重写 onFail(Throwable t)方法,并且不调用 super.onFail(Throwable t),那么就不会走统一处理的方式。

解决场景三的需求:

这里就是一个网络请求慢,但是界面已经关闭的处理需求。
SICallBack里面默认对Activity进行了判断,如果界面已经关闭,那么就算成功之后,还去更新界面UI已经失去意义,所以不会去执行onSuccess ,onFail,onFinally,方法。

@Override
public void onFailure(Call<T> call, Throwable t)
{
    if (checkActivityFinish())
        return;
    try
    {
        onFail(t);
    } finally
    {
        onFinally();
    }
}
  • SICallBack里面,默认已经对本需求进行了处理。

解决场景四的需求:

这个需求在很多APP里面都需要这种功能,有的人称之为路由之间的跳转。这里给一个例子:

import android.content.Context;
import android.support.annotation.Nullable;
import android.util.Log;

import com.xiaolei.exretrofitcallback.network.regist.OnCallBack;
import com.xiaolei.exretrofitcallback.network.regist.ResponseBeanRegister;
import com.xiaolei.exretrofitcallbackexample.Net.DataBean;

/**
 * 这里是对地址进行拦截
 * 如果是兰州市的地址,运行兰州市的方法,且不再执行onSuccess方法。
 * 如果是深圳市的地址,运行深圳市的方法,不拦截,继续执行onSuccess方法。
 * Created by xiaolei on 2017/12/15.
 */

public class MyRegister extends ResponseBeanRegister<DataBean>
{
    @Nullable
    @Override
    public String filter(DataBean bean)
    {
        return bean.getLat();
    }
    
    @OnCallBack(value = "36.06108")//兰州市
    public void onInLanzhou(Context context)
    {
        Log.d("MainActivity", "拦截:兰州市");
    }

    @OnCallBack(value = "22.54309",stopNextStep = false)//深圳市
    public void onInShenzhen(Context context)
    {
        Log.d("MainActivity", "拦截:深圳市");
    }
    
}
  • 1、 :新建一个类,继承ResponseBeanRegister<T>,泛型里,则写上你的本地请求返回数据的类型,比如:一个Bean,或者,String 字符串。
  • 2、 :你的每次网络请求成功后都会自动调用这个onfilter方法,所以需要重写String filter(T bean);方法。返回的数据则是你需要去判断的数据。比如:你的泛型是DataBean,你需要判断DataBean里面 lat字段的值,那么你就应该这么写:
@Nullable
@Override
public String filter(DataBean bean)
{
    return bean.getLat();
}
  • 3、 : 定义一个方法,使用用@OnCallBack去注解,示例如下:
@OnCallBack(value = "22.54309",stopNextStep = false)//深圳市
public void onInShenzhen(Context context)
{
    Log.d("MainActivity", "拦截:深圳市");
}

这里有2个需要注意的:
①:OnCallBack里面,有两个参数,第一个参数value是用来比较的值,当onfilter方法返回的值等于value的时候,则会自动调用当前方法,第二个参数stopNextStep是一个布尔值,不写默认为true。当为true的时候,则当调用完本方法,不再调用onSuccess方法。当为false,则会继续调用onSuccess方法。

stopNextStep = false -> 本方法 -> onSuccess -> onFinally
stopNextStep = true -> 本方法 -> onFinally

②:对于定义的方法的参数,支持两个,一个是CallBack的返回的参数,一个则是Context上下文。


支持自动注入值的参数类型
  • 4、 :在Config里注册:Config.registResponseBean(DataBean.class,MyRegister.class);//路由之间跳转的注册 。可注册多个Bean以及对应的ResponseRegister.

结尾

移步这里获取Demo以及完整关键源码:
Gtihub:https://github.com/xiaolei123/ExRetrofitCallback

gradle直接使用:

compile 'com.xiaolei:ExRetrofitCallBack:1.0.1'
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,509评论 6 504
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,806评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,875评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,441评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,488评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,365评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,190评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,062评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,500评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,706评论 3 335
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,834评论 1 347
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,559评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,167评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,779评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,912评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,958评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,779评论 2 354

推荐阅读更多精彩内容