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, "failureThrowablenull”);
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, "tagnull”);
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 处理动画
这里重写parseThrowable处理一些Callback2中为未处理的异常
public abstract class AnimCallback extends Callback2 {
private ILoadingView mLoadingView;
public AnimCallback(@Nullable ILoadingView loadingView) {
this.mLoadingView = loadingView;
}
@Override
public void onStart(Call2<T> call2) {
if (mLoadingView != null)
mLoadingView.showLoading();
}
@Override
public void onCompleted(Call2<T> call2, @Nullable Throwable t, boolean canceled) {
if (canceled)
return;
if (mLoadingView != null)
mLoadingView.hideLoading();
}
@NonNull
@Override
public HttpError parseThrowable(Call2<T> call2, Throwable t) {
HttpError filterError;
if (t instanceof JsonSyntaxException) {
filterError = new HttpError(“解析异常”, t);
} else {
filterError = super.parseThrowable(call2, t);
}
return filterError;
}
}
#####3.5 发起请求
RetrofitFactory.create(ApiService.class)
.getLogin(“xxxxx”, “123456”)
.enqueue(hashCode(), new AnimCallback(this) {
@Override
public void onError(Call2 call2, HttpError error) {
//处理失败
}
@Override
public void onSuccess(Call2<LoginInfo> call2, LoginInfo response) {
//处理成功 如保存登录信息等
}
});
//在onDestor中取消未结束的请求
@Override
protected void onDestroy() {
super.onDestroy();
//hashCode() 能保证唯一性,取消当前页面所发起的所有请求,只要
// enqueue(tag, callback2) 传入的是对应的hashCode() 即可
CallManager.getInstance().cancel(hashCode());
}
###4.注意事项
#####4.1 构建retrofit是需要ExecutorCallAdapterFactory实例,否则无法处理返回为Call2的服务接口
#####4.2 Callback2的回调函数均在主线程执行,如果调用了Call2.cancel()方法,除了onCompleted()方法会执行外其他回调方法都不会执行
###5.下载
implementation “com.xcheng:retrofit-helper:1.0.0”\
retrofit-helper GitHub地址:
https://github.com/xchengDroid/retrofit-helper
Copyright 2019 xchengDroid
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数初中级Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则近万的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注:Android)
![](https://i-blog.csdnimg.cn/blog_migrate/ff2a53a57ed9b806a51e115d09803564.jpeg)
写在最后
最后我想说:对于程序员来说,要学习的知识内容、技术有太多太多,要想不被环境淘汰就只有不断提升自己,从来都是我们去适应环境,而不是环境来适应我们!
这里附上上述的技术体系图相关的几十套腾讯、头条、阿里、美团等公司2021年的面试题,把技术点整理成了视频和PDF(实际上比预期多花了不少精力),包含知识脉络 + 诸多细节,由于篇幅有限,这里以图片的形式给大家展示一部分。
相信它会给大家带来很多收获:
当程序员容易,当一个优秀的程序员是需要不断学习的,从初级程序员到高级程序员,从初级架构师到资深架构师,或者走向管理,从技术经理到技术总监,每个阶段都需要掌握不同的能力。早早确定自己的职业方向,才能在工作和能力提升中甩开同龄人。
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!
从来都是我们去适应环境,而不是环境来适应我们!**
这里附上上述的技术体系图相关的几十套腾讯、头条、阿里、美团等公司2021年的面试题,把技术点整理成了视频和PDF(实际上比预期多花了不少精力),包含知识脉络 + 诸多细节,由于篇幅有限,这里以图片的形式给大家展示一部分。
相信它会给大家带来很多收获:
[外链图片转存中…(img-4TlcMRyV-1713407135990)]
[外链图片转存中…(img-8ocPA52r-1713407135991)]
当程序员容易,当一个优秀的程序员是需要不断学习的,从初级程序员到高级程序员,从初级架构师到资深架构师,或者走向管理,从技术经理到技术总监,每个阶段都需要掌握不同的能力。早早确定自己的职业方向,才能在工作和能力提升中甩开同龄人。
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!