retrofit-helper-简洁的封装retrofit,优雅的取消请求

return new HttpError(“响应超时”, t);
} else {
return new HttpError(“请求失败”, t);
}
}

public abstract void onError(Call2<T> call2, HttpError error);

public abstract void onSuccess(Call2<T> call2, T response);

/**

  • @param t 请求失败的错误信息
  • @param canceled 请求是否被取消了
    */
    public abstract void onCompleted(Call2<T> call2, @Nullable Throwable t, boolean canceled);
    }

#####2.4 HttpError 统一处理异常错误

HttpError类中有两个成员属性msg 被body,msg是保存错误的描述信息等,body可以保存异常的具体信息或者原始的json等,onError(Call2 call2, HttpError error)回调方法可以根据body的具体信息做二次处理。

/**

  • 通用的错误信息,一般请求是失败只需要弹出一些错误信息即可,like{@link retrofit2.HttpException}
  • Created by chengxin on 2017/6/22.
    /
    public final class HttpError extends RuntimeException {
    private static final long serialVersionUID = -134024482758434333L;
    /
    *
  • 展示在前端的错误描述信息
    /
    public String msg;
    /
    *
  • <p>
  • 请求失败保存失败信息,for example:
  • <li>BusiModel: {code:xxx,msg:xxx} 业务错误信息</li>
  • <li>original json: 原始的json</li>
  • <li>{@link retrofit2.Response}:错误响应体->Response<?></li>
  • <li>Throwable: 抛出的异常信息</li>
  • </p>
    */
    @Nullable
    public final transient Object body;

public HttpError(String msg) {
this(msg, null);
}

public HttpError(String msg, @Nullable Object body) {
super(msg);
if (body instanceof Throwable) {
initCause((Throwable) body);
}
//FastPrintWriter#print(String str)
this.msg = msg != null ? msg : “null”;
this.body = body;
}

/**

  • 保证和msg一致
    */
    @Override
    public String getMessage() {
    return msg;
    }

@Override
public String toString() {
return “HttpError {msg=”

  • msg
  • “, body=”
  • body
  • ‘}’;
    }
    }

#####2.5 ExecutorCallAdapterFactory返回Call2请求适配器

处理请求接口方法返回为Call2的请求适配器工厂类

public final class ExecutorCallAdapterFactory extends CallAdapter.Factory {
public static final CallAdapter.Factory INSTANCE = new ExecutorCallAdapterFactory();

private ExecutorCallAdapterFactory() {
}

/**

  • Extract the raw class type from {@code type}. For example, the type representing
  • {@code List<? extends Runnable>} returns {@code List.class}.
    */
    public static Class<?> getRawType(Type type) {
    return CallAdapter.Factory.getRawType(type);
    }

@Override
public CallAdapter<?, ?> get(Type returnType, Annotation[] annotations, Retrofit retrofit) {
if (getRawType(returnType) != Call2.class) {
return null;
}
if (!(returnType instanceof ParameterizedType)) {
throw new IllegalArgumentException(
“Call return type must be parameterized as Call2<Foo> or Call2<? extends Foo>”);
}
final Type responseType = getParameterUpperBound(0, (ParameterizedType) returnType);

final Executor callbackExecutor = retrofit.callbackExecutor();
if (callbackExecutor == null) throw new AssertionError();

return new CallAdapter<Object, Call<?>>() {
@Override
public Type responseType() {
return responseType;
}

@Override
public Call<Object> adapt(Call<Object> call) {
return new ExecutorCallbackCall2<>(callbackExecutor, call);
}
};
}
}

#####2.6 ExecutorCallbackCall2 继承Call2代理OkHttpCall处理UI回调

装饰者模式代理OkHttpCall的所有方法,线程调度处理 Callback2 的回调方法在主线程执行

final class ExecutorCallbackCall2 implements Call2 {
private final Executor callbackExecutor;
private final Call delegate;
/**

  • The executor used for {@link Callback} methods on a {@link Call}. This may be {@code null},
  • in which case callbacks should be made synchronously on the background thread.
    */
    ExecutorCallbackCall2(Executor callbackExecutor, Call<T> delegate) {
    this.callbackExecutor = callbackExecutor;
    this.delegate = delegate;
    }

@Override
public void enqueue(final Callback<T> callback) {
throw new UnsupportedOperationException(“please call enqueue(Object tag, Callback2<T> callback2)”);
}

@Override
public void enqueue(@Nullable Object tag, final Callback2<T> callback2) {
Utils.checkNotNull(callback2, “callback2==null”);
CallManager.getInstance().add(this, tag != null ? tag : “NO_TAG”);
callbackExecutor.execute(new Runnable() {
@Override
public void run() {
if (!isCanceled()) {
callback2.onStart(ExecutorCallbackCall2.this);
}
}
});

delegate.enqueue(new Callback<T>() {
@Override
public void onResponse(Call<T> call, final Response<T> response) {
callbackExecutor.execute(new Runnable() {
@Override
public void run() {
callResult(callback2, response, null);
}
});
}

@Override
public void onFailure(Call<T> call, final Throwable t) {
callbackExecutor.execute(new Runnable() {
@Override
public void run() {
callResult(callback2, null, t);
}
});
}
});
}

@UiThread
private void callResult(Callback2<T> callback2, @Nullable Response<T> response, @Nullable Throwable failureThrowable) {
try {
if (!isCanceled()) {
//1、获取解析结果
Result<T> result;
if (response != null) {
result = callback2.parseResponse(this, response);
Utils.checkNotNull(result, “resultnull");
} else {
Utils.checkNotNull(failureThrowable, "failureThrowable
null”);
HttpError error = callback2.parseThrowable(this, failureThrowable);
result = Result.error(error);
}
//2、回调成功失败
if (result.isSuccess()) {
callback2.onSuccess(this, result.body());
} else {
callback2.onError(this, result.error());
}
}
callback2.onCompleted(this, failureThrowable, isCanceled());
} finally {
CallManager.getInstance().remove(this);
}
}

@Override
public boolean isExecuted() {
return delegate.isExecuted();
}

@Override
public Response<T> execute() throws IOException {
return delegate.execute();
}

@Override
public void cancel() {
delegate.cancel();
}

@Override
public boolean isCanceled() {
return delegate.isCanceled();
}

@SuppressWarnings(“CloneDoesntCallSuperClone”) // Performing deep clone.
@Override
public Call2<T> clone() {
return new ExecutorCallbackCall2<>(callbackExecutor, delegate.clone());
}

@Override
public Request request() {
return delegate.request();
}
}

#####2.7 CallManager统一管理请求,取消请求

全局保存所有的请求,添加 、删除请求,取消某个某些匹配tag的请求。可以在Activity 或Fragment的销毁方法中调用CallManager.getInstance().cancel( yourTag )

/**

  • 创建时间:2018/5/31
  • 编写人: chengxin
  • 功能描述:全局管理Call请求管理,just like {@link okhttp3.Dispatcher}
    */
    public final class CallManager implements ActionManager<Call<?>> {
    @GuardedBy(“this”)
    private final List callTags = new ArrayList<>(4);
    private volatile static CallManager instance;
    private CallManager() {
    }

public static CallManager getInstance() {
if (instance == null) {
synchronized (CallManager.class) {
if (instance == null) {
instance = new CallManager();
}
}
}
return instance;
}

@Override
public synchronized void add(Call<?> call, Object tag) {
Utils.checkState(!contains(call), “Call<?> " + call + " is already added.”);
callTags.add(new CallTag(call, tag));
}

/**

  • 当call结束时移除
  • @param call Retrofit Call
    */
    @Override
    public synchronized void remove(Call<?> call) {
    if (callTags.isEmpty())
    return;
    for (int index = 0; index < callTags.size(); index++) {
    if (call == callTags.get(index).call) {
    //like okhttp3.Headers#removeAll(String name)
    //remove(int index) 方法优于 remove(Object o),无需再次遍历
    callTags.remove(index);
    break;
    }
    }
    }

/**

  • 取消并移除对应tag的call,确保Call被取消后不再被引用,
  • 结合{@link #remove(Call)}方法双保险
  • @param tag call对应的tag
    */
    @Override
    public synchronized void cancel(final @Nullable Object tag) {
    if (callTags.isEmpty())
    return;
    if (tag != null) {
    for (int index = 0; index < callTags.size(); index++) {
    CallTag callTag = callTags.get(index);
    if (callTag.tag.equals(tag)) {
    callTag.call.cancel();
    callTags.remove(index);
    index–;
    }
    }
    } else {
    for (CallTag callTag : callTags) {
    callTag.call.cancel();
    }
    callTags.clear();
    }
    }

@Override
public synchronized boolean contains(Call<?> call) {
for (CallTag callTag : callTags) {
if (call == callTag.call) {
return true;
}
}
return false;
}

/**

  • 保存call和tag
    */
    final static class CallTag {
    private final Call<?> call;
    private final Object tag;

CallTag(Call<?> call, Object tag) {
Utils.checkNotNull(call == null, “callnull");
Utils.checkNotNull(tag == null, "tag
null”);
this.call = call;
this.tag = tag;
}
}
}

#####2.8 ProgressInterceptor 拦截器监听下载和上传进度

继承okhttp3.Interceptor ,构造方法中传入ProgressListener监听进度

/**

  • 创建时间:2018/8/2
  • 编写人: chengxin
  • 功能描述:上传或下载进度监听拦截器
    */
    public class ProgressInterceptor implements Interceptor {
    private final ProgressListener mProgressListener;

public ProgressInterceptor(ProgressListener progressListener) {
Utils.checkNotNull(progressListener, “progressListener==null”);
this.mProgressListener = progressListener;
}

@Override
public Response intercept(Chain chain) throws IOException {
Request request = chain.request();
RequestBody requestBody = request.body();
//判断是否有上传需求
if (requestBody != null && requestBody.contentLength() > 0) {
Request.Builder builder = request.newBuilder();
RequestBody newRequestBody = new ProgressRequestBody(requestBody, mProgressListener, request);
request = builder.method(request.method(), newRequestBody).build();
}

Response response = chain.proceed(request);
ResponseBody responseBody = response.body();
if (responseBody != null && responseBody.contentLength() > 0) {
Response.Builder builder = response.newBuilder();
ResponseBody newResponseBody = new ProgressResponseBody(responseBody, mProgressListener, request);
response = builder.body(newResponseBody).build();
}
return response;
}
}

2.9 HttpLoggingInterceptor 可以单独指定某个请求的日志级别

构造OkhttpClient时添加此拦截器,在请求的服务方法中添加注解

@Headers(“LogLevel:NONE”) 或 @Headers(“LogLevel:BASIC”) 或 @Headers(“LogLevel:HEADERS”) 或@Headers(“LogLevel:BODY”)

@FormUrlEncoded
@Headers(“LogLevel:HEADERS”)
@POST(“user/login”)
Call2 getLogin(@Field(“username”) String username, @Field(“password”) String password);

###3.实战

#####3.1 初始化全局Retrofit对象

Retrofit retrofit = new Retrofit.Builder()
.baseUrl(“http://wanandroid.com/”)
.callFactory(new OkHttpClient.Builder()
.addNetworkInterceptor(httpLoggingInterceptor)
.build())
//必须添加此adapter 用于构建处理回调
.addCallAdapterFactory(ExecutorCallAdapterFactory.INSTANCE)
//添加自定义json解析器
.addConverterFactory(GsonConverterFactory.create())
.build();
RetrofitFactory.DEFAULT = retrofit;

//可以添加多个,如:
RetrofitFactory.OTHERS.put(“other”,otherRetrofit);

#####3.2 添加请求服务接口

下面为登录的 post请求

@FormUrlEncoded
@POST(“user/login”)
Call2 getLogin(@Field(“username”) String username, @Field(“password”) String password);

######3.3 添加ILoadingView,用于开启和结束动画

Activity 或者Fragment 可以继承 ILoadingView接口实现开始和结束动画

public interface ILoadingView {
/**

  • 显示加载
    /
    void showLoading();
    /
    *
  • 隐藏加载
    */
    void hideLoading();
    }

#####3.4 添加AnimCallback 处理动画

自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。

深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!

因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

img

img

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!

由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!

如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)

最后为了帮助大家深刻理解Android相关知识点的原理以及面试相关知识,这里放上我搜集整理的2019-2021BATJ 面试真题解析,我把大厂面试中常被问到的技术点整理成了PDF,包知识脉络 + 诸多细节。

节省大家在网上搜索资料的时间来学习,也可以分享给身边好友一起学习。

《960全网最全Android开发笔记》

《379页Android开发面试宝典》

历时半年,我们整理了这份市面上最全面的安卓面试题解析大全
包含了腾讯、百度、小米、阿里、乐视、美团、58、猎豹、360、新浪、搜狐等一线互联网公司面试被问到的题目。熟悉本文中列出的知识点会大大增加通过前两轮技术面试的几率。

如何使用它?

1.可以通过目录索引直接翻看需要的知识点,查漏补缺。
2.五角星数表示面试问到的频率,代表重要推荐指数

《507页Android开发相关源码解析》

只要是程序员,不管是Java还是Android,如果不去阅读源码,只看API文档,那就只是停留于皮毛,这对我们知识体系的建立和完备以及实战技术的提升都是不利的。

真正最能锻炼能力的便是直接去阅读源码,不仅限于阅读各大系统源码,还包括各种优秀的开源库。

腾讯、字节跳动、阿里、百度等BAT大厂 2019-2021面试真题解析

资料太多,全部展示会影响篇幅,暂时就先列举这些部分截图

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

代表重要推荐指数

[外链图片转存中…(img-dvrSfIfG-1712796974940)]

《507页Android开发相关源码解析》

只要是程序员,不管是Java还是Android,如果不去阅读源码,只看API文档,那就只是停留于皮毛,这对我们知识体系的建立和完备以及实战技术的提升都是不利的。

真正最能锻炼能力的便是直接去阅读源码,不仅限于阅读各大系统源码,还包括各种优秀的开源库。

[外链图片转存中…(img-hSv1mwGz-1712796974940)]

腾讯、字节跳动、阿里、百度等BAT大厂 2019-2021面试真题解析

[外链图片转存中…(img-kSbuzpNF-1712796974940)]

资料太多,全部展示会影响篇幅,暂时就先列举这些部分截图

《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!

  • 19
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
retrofit-spring-boot-starter是一个用于整合Retrofit库和Spring Boot的starter项目,它可以简化在Spring Boot中使用Retrofit的配置和使用。 以下是retrofit-spring-boot-starter的使用方法: 1. 在你的Spring Boot项目的pom.xml文件中添加以下依赖: ```xml <dependency> <groupId>com.github.lianjiatech</groupId> <artifactId>retrofit-spring-boot-starter</artifactId> <version>1.0.0</version> </dependency> ``` 2. 创建一个接口,用于定义Retrofit的API接口。例如: ```java import retrofit2.http.GET; import retrofit2.http.Path; public interface MyApi { @GET("/users/{username}") User getUser(@Path("username") String username); } ``` 3. 在你的Spring Boot应用程序中,使用`@Autowired`注解将Retrofit的API接口注入到你的代码中。例如: ```java import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import retrofit2.Retrofit; @Service public class MyService { private final MyApi myApi; @Autowired public MyService(Retrofit retrofit) { this.myApi = retrofit.create(MyApi.class); } public User getUser(String username) { return myApi.getUser(username); } } ``` 4. 现在你可以在你的代码中使用`MyService`来调用Retrofit的API接口了。例如: ```java import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RestController; @RestController public class MyController { private final MyService myService; @Autowired public MyController(MyService myService) { this.myService = myService; } @GetMapping("/users/{username}") public User getUser(@PathVariable String username) { return myService.getUser(username); } } ``` 以上是retrofit-spring-boot-starter的基本用法。你可以根据自己的需求进行配置和使用。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值