首先我们来思考几个场景:
以上场景是我们在APP开发中经常遇到的情况,那么我们接下来的代码,就是要解决这样的需求,我们要用最少的代码来完成最绕的需求。
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");
}
});
Context
Fragment
v4.app.Fragment
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();
}
}
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();
}
}
这个需求在很多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", "拦截:深圳市");
}
}
ResponseBeanRegister<T>
,泛型里,则写上你的本地请求返回数据的类型,比如:一个Bean,或者,String 字符串。onfilter
方法,所以需要重写String filter(T bean);
方法。返回的数据则是你需要去判断的数据。比如:你的泛型是DataBean,你需要判断DataBean里面 lat字段的值,那么你就应该这么写:@Nullable
@Override
public String filter(DataBean bean)
{
return bean.getLat();
}
@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上下文。
支持自动注入值的参数类型
Config.registResponseBean(DataBean.class,MyRegister.class);//路由之间跳转的注册
。可注册多个Bean以及对应的ResponseRegister.移步这里获取Demo以及完整关键源码: Gtihub:https://github.com/xiaolei123/ExRetrofitCallback
gradle直接使用:
compile 'com.xiaolei:ExRetrofitCallBack:1.0.1'