当前位置: 首页 > news >正文

昆明云南微网站互联网推广营销方案

昆明云南微网站,互联网推广营销方案,梅州网站开发baidu,徐州网站建设开发Retrofit的基本使用流程很简洁,但是简洁并不代表简单,Retrofit为了实现这种简洁的使用流程,内部使用了优秀的架构设计和大量的设计模式,在我分析过Retrofit最新版的源码和大量优秀的Retrofit源码分析文章后,我发现&…

Retrofit的基本使用流程很简洁,但是简洁并不代表简单,Retrofit为了实现这种简洁的使用流程,内部使用了优秀的架构设计和大量的设计模式,在我分析过Retrofit最新版的源码和大量优秀的Retrofit源码分析文章后,我发现,要想真正理解Retrofit内部的核心源码流程和设计思想,首先,需要对这九大设计模式有一定的了解,如下:

1.Retrofit构建过程

建造者模式、工厂方法模式

2.创建网络请求接口实例过程

外观模式、代理模式、单例模式、策略模式、装饰模式(建造者模式)

3.生成并执行请求过程

适配器模式(代理模式、装饰模式)

复制代码

其次,需要对OKHttp源码有一定的了解,如果不了解的可以看看这篇Android主流三方库源码分析(一、深入理解OKHttp源码)。最后,让我们按以上流程去深入Retrofit源码内部,领悟它带给我们的设计之美

二、Retrofit构建过程

1、Retrofit核心对象解析

首先Retrofit中有一个全局变量非常关键,在V2.5之前的版本,使用的是LinkedHashMap(),它是一个网络请求配置对象,是由网络请求接口中方法注解进行解析后得到的。

public final class Retrofit {

// 网络请求配置对象,存储网络请求相关的配置,如网络请求的方法、数据转换器、网络请求适配器、网络请求工厂、基地址等

private final Map<Method, ServiceMethod<?>> serviceMethodCache = new ConcurrentHashMap<>();

复制代码

Retrofit使用了建造者模式通过内部类Builder类建立一个Retrofit实例,如下:

public static final class Builder {

// 平台类型对象(Platform -> Android)

private final Platform platform;

// 网络请求工厂,默认使用OkHttpCall(工厂方法模式)

private @Nullable okhttp3.Call.Factory callFactory;

// 网络请求的url地址

private @Nullable HttpUrl baseUrl;

// 数据转换器工厂的集合

private final List<Converter.Factory> converterFactories = new ArrayList<>();

// 网络请求适配器工厂的集合,默认是ExecutorCallAdapterFactory

private final List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>();

// 回调方法执行器,在 Android 上默认是封装了 handler 的 MainThreadExecutor, 默认作用是:切换线程(子线程 -> 主线程)

private @Nullable Executor callbackExecutor;

// 一个开关,为true则会缓存创建的ServiceMethod

private boolean validateEagerly;

复制代码

2、Builder内部构造

下面看看Builder内部构造做了什么。

public static final class Builder {

Builder(Platform platform) {

this.platform = platform;

}

public Builder() {

this(Platform.get());

}

}

class Platform {

private static final Platform PLATFORM = findPlatform();

static Platform get() {

return PLATFORM;

}

private static Platform findPlatform() {

try {

// 使用JVM加载类的方式判断是否是Android平台

Class.forName(“android.os.Build”);

if (Build.VERSION.SDK_INT != 0) {

return new Android();

}

} catch (ClassNotFoundException ignored) {

}

try {

// 同时支持Java平台

Class.forName(“java.util.Optional”);

return new Java8();

} catch (ClassNotFoundException ignored) {

}

return new Platform();

}

static class Android extends Platform {

@Override public Executor defaultCallbackExecutor() {

//切换线程(子线程 -> 主线程)

return new MainThreadExecutor();

}

// 创建默认的网络请求适配器工厂,如果是Android7.0或Java8上,则使

// 用了并发包中的CompletableFuture保证了回调的同步

// 在Retrofit中提供了四种CallAdapterFactory(策略模式):

// ExecutorCallAdapterFactory(默认)、GuavaCallAdapterFactory、

// va8CallAdapterFactory、RxJavaCallAdapterFactory

@Override List<? extends CallAdapter.Factory> defaultCallAdapterFactories(

@Nullable Executor callbackExecutor) {

if (callbackExecutor == null) throw new AssertionError();

ExecutorCallAdapterFactory executorFactory = new ExecutorCallAdapterFactory(callbackExecutor);

return Build.VERSION.SDK_INT >= 24

? asList(CompletableFutureCallAdapterFactory.INSTANCE, executorFactory)
singletonList(executorFactory);

}

@Override List<? extends Converter.Factory> defaultConverterFactories() {

return Build.VERSION.SDK_INT >= 24

? singletonList(OptionalConverterFactory.INSTANCE)
Collections.<Converter.Factory>emptyList();

}

static class MainThreadExecutor implements Executor {

// 获取Android 主线程的Handler

private final Handler handler = new Handler(Looper.getMainLooper());

@Override public void execute(Runnable r) {

// 在UI线程对网络请求返回数据处理

handler.post®;

}

}

}

复制代码

可以看到,在Builder内部构造时设置了默认Platform、callAdapterFactories和callbackExecutor。

3、添加baseUrl

很简单,就是将String类型的url转换为OkHttp的HttpUrl过程如下:

/**

  • Set the API base URL.

  • @see #baseUrl(HttpUrl)

*/

public Builder baseUrl(String baseUrl) {

checkNotNull(baseUrl, “baseUrl == null”);

return baseUrl(HttpUrl.get(baseUrl));

}

public Builder baseUrl(HttpUrl baseUrl) {

checkNotNull(baseUrl, “baseUrl == null”);

List pathSegments = baseUrl.pathSegments();

if (!“”.equals(pathSegments.get(pathSegments.size() - 1))) {

throw new IllegalArgumentException("baseUrl must end in /: " + baseUrl);

}

this.baseUrl = baseUrl;

return this;

}

复制代码

4、添加GsonConverterFactory

首先,看到GsonConverterFactory.creat()的源码。

public final class GsonConverterFactory extends Converter.Factory {

public static GsonConverterFactory create() {

return create(new Gson());

}

public static GsonConverterFactory create(Gson gson) {

if (gson == null) throw new NullPointerException(“gson == null”);

return new GsonConverterFactory(gson);

}

private final Gson gson;

// 创建了一个含有Gson对象实例的GsonConverterFactory

private GsonConverterFactory(Gson gson) {

this.gson = gson;

}

复制代码

然后,看看addConverterFactory()方法内部。

public Builder addConverterFactory(Converter.Factory factory) {

converterFactories.add(checkNotNull(factory, “factory null”));

return this;

}

复制代码

可知,这一步是将一个含有Gson对象实例的GsonConverterFactory放入到了数据转换器工厂converterFactories里。

5、build过程

public Retrofit build() {

if (baseUrl == null) {

throw new IllegalStateException(“Base URL required.”);

}

okhttp3.Call.Factory callFactory = this.callFactory;

if (callFactory == null) {

// 默认使用okhttp

callFactory = new OkHttpClient();

}

Executor callbackExecutor = this.callbackExecutor;

if (callbackExecutor == null) {

// Android默认的callbackExecutor

callbackExecutor = platform.defaultCallbackExecutor();

}

// Make a defensive copy of the adapters and add the defaultCall adapter.

List<CallAdapter.Factory> callAdapterFactories = new ArrayList<>(this.callAdapterFactories);

// 添加默认适配器工厂在集合尾部

callAdapterFactories.addAll(platform.defaultCallAdapterFactorisca llbackExecutor));

// Make a defensive copy of the converters.

List<Converter.Factory> converterFactories = new ArrayList<>(

1 + this.converterFactories.size() + platform.defaultConverterFactoriesSize());

// Add the built-in converter factory first. This prevents overriding its behavior but also

// ensures correct behavior when using converters thatconsumeall types.

converterFactories.add(new BuiltInConverters());

converterFactories.addAll(this.converterFactories);

converterFactories.addAll(platform.defaultConverterFactories();

return new Retrofit(callFactory, baseUrl, unmodifiableList(converterFactories),

unmodifiableList(callAdapterFactories), callbackExecutor, validateEagerly);

}

复制代码

可以看到,最终我们在Builder类中看到的6大核心对象都已经配置到Retrofit对象中了。

三、创建网络请求接口实例过程

retrofit.create()使用了外观模式和代理模式创建了网络请求的接口实例,我们分析下create方法。

public T create(final Class service) {

Utils.validateServiceInterface(service);

if (validateEagerly) {

// 判断是否需要提前缓存ServiceMethod对象

eagerlyValidateMethods(service);

}

// 使用动态代理拿到请求接口所有注解配置后,创建网络请求接口实例

return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service },

new InvocationHandler() {

private final Platform platform = Platform.get();

private final Object[] emptyArgs = new Object[0];

@Override public Object invoke(Object proxy, Method method, @Nullable Object[] args)

throws Throwable {

// If the method is a method from Object then defer to normal invocation.

if (method.getDeclaringClass() == Object.class) {

return method.invoke(this, args);

}

if (platform.isDefaultMethod(method)) {

return platform.invokeDefaultMethod(method, service, proxy, args);

}

return loadServiceMethod(method).invoke(args != null ? args : emptyArgs);

}

});

}

private void eagerlyValidateMethods(Class<?> service) {

Platform platform = Platform.get();

for (Method method : service.getDeclaredMethods()) {

if (!platform.isDefaultMethod(method)) {

loadServiceMethod(method);

}

}

}

复制代码

继续看看loadServiceMethod的内部流程

ServiceMethod<?> loadServiceMethod(Method method) {

ServiceMethod<?> result = serviceMethodCache.get(method);

if (result != null) return result;

synchronized (serviceMethodCache) {

result = serviceMethodCache.get(method);

if (result == null) {

// 解析注解配置得到了ServiceMethod

result = ServiceMethod.parseAnnotations(this, method);

// 可以看到,最终加入到ConcurrentHashMap缓存中

serviceMethodCache.put(method, result);

}

}

return result;

}

abstract class ServiceMethod {

static ServiceMethod parseAnnotations(Retrofit retrofit, Method method) {

// 通过RequestFactory解析注解配置(工厂模式、内部使用了建造者模式)

RequestFactory requestFactory = RequestFactory.parseAnnotations(retrofit, method);

Type returnType = method.getGenericReturnType();

if (Utils.hasUnresolvableType(returnType)) {

throw methodError(method,

“Method return type must not include a type variable or wildcard: %s”, returnType);

}

if (returnType == void.class) {

throw methodError(method, “Service methods cannot return void.”);

}

// 最终是通过HttpServiceMethod构建的请求方法

return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);

}

abstract T invoke(Object[] args);

}

复制代码

以下为请求构造核心流程

根据RequestFactory#Builder构造方法和parseAnnotations方法的源码,可知的它的作用就是用来解析注解配置的。

Builder(Retrofit retrofit, Method method) {

this.retrofit = retrofit;

this.method = method;

// 获取网络请求接口方法里的注释

this.methodAnnotations = method.getAnnotations();

// 获取网络请求接口方法里的参数类型

this.parameterTypes = method.getGenericParameterTypes();

// 获取网络请求接口方法里的注解内容

this.parameterAnnotationsArray = method.getParameterAnnotations();

}

复制代码

接着看HttpServiceMethod.parseAnnotations()的内部流程。

static <ResponseT, ReturnT> HttpServiceMethod<ResponseT, ReturnT> parseAnnotations(

Retrofit retrofit, Method method, RequestFactory requestFactory) {

//1.根据网络请求接口方法的返回值和注解类型,

// 从Retrofit对象中获取对应的网络请求适配器

CallAdapter<ResponseT, ReturnT> callAdapter = createCallAdapter(retrofit,method);

// 得到响应类型

Type responseType = callAdapter.responseType();

//2.根据网络请求接口方法的返回值和注解类型从Retrofit对象中获取对应的数据转换器

Converter<ResponseBody, ResponseT>responseConverter =

createResponseConverter(retrofit,method, responseType);

okhttp3.Call.Factory callFactory = retrofit.callFactory;

return newHttpServiceMethod<>(requestFactory, callFactory, callAdapter,responseConverter);

}

复制代码

1.createCallAdapter(retrofit, method)

private static <ResponseT, ReturnT> CallAdapter<ResponseT, ReturnT> createCallAdapter(

Retrofit retrofit, Method method) {

// 获取网络请求接口里方法的返回值类型

Type returnType = method.getGenericReturnType();

// 获取网络请求接口接口里的注解

Annotation[] annotations = method.getAnnotations();

try {

//noinspection unchecked

return (CallAdapter<ResponseT, ReturnT>) retrofit.callAdapter(returnType, annotations);

} catch (RuntimeException e) { // Wide exception range because factories are user code.

throw methodError(method, e, “Unable to create call adapter for %s”, returnType);

}

}

public CallAdapter<?, ?> callAdapter(Type returnType, Annotation[] annotations) {

return nextCallAdapter(null, returnType, annotations);

}

public CallAdapter<?, ?> nextCallAdapter(@Nullable CallAdapter.Factory skipPast, Type returnType,

Annotation[] annotations) {

int start = callAdapterFactories.indexOf(skipPast) + 1;

// 遍历 CallAdapter.Factory 集合寻找合适的工厂

for (int i = start, count = callAdapterFactories.size(); i <count; i++) {

CallAdapter<?, ?> adapter = callAdapterFactories.get(i).get(returnType, annotations, this);

if (adapter != null) {

return adapter;

}

}

}

复制代码

2.createResponseConverter(Retrofit retrofit, Method method, Type responseType)

private static Converter<ResponseBody, ResponseT> createResponseConverter(

Retrofit retrofit, Method method, Type responseType) {

Annotation[] annotations = method.getAnnotations();

try {

return retrofit.responseBodyConverter(responseType,annotations);

} catch (RuntimeException e) { // Wide exception range because factories are user code.

throw methodError(method, e, “Unable to create converter for%s”, responseType);

}

}

public Converter<ResponseBody, T> responseBodyConverter(Type type, Annotation[] annotations) {

return nextResponseBodyConverter(null, type, annotations);

}

public Converter<ResponseBody, T> nextResponseBodyConverter(

@Nullable Converter.Factory skipPast, Type type, Annotation[] annotations) {

int start = converterFactories.indexOf(skipPast) + 1;

// 遍历 Converter.Factory 集合并寻找合适的工厂, 这里是GsonResponseBodyConverter

for (int i = start, count = converterFactories.size(); i < count; i++) {

Converter<ResponseBody, ?> converter =

converterFactories.get(i).responseBodyConverter(type, annotations, this);

if (converter != null) {

//noinspection unchecked

return (Converter<ResponseBody, T>) converter;

}

}

复制代码

最终,执行HttpServiceMethod的invoke方法

@Override ReturnT invoke(Object[] args) {

return callAdapter.adapt(

new OkHttpCall<>(requestFactory, args, callFactory, responseConverter));

}

复制代码

最终在adapt中创建了一个ExecutorCallbackCall对象,它是一个装饰者,而在它内部真正去执行网络请求的还是OkHttpCall。

四、创建网络请求接口类实例并执行请求过程

1、service.listRepos()

1、Call<List> repos = service.listRepos(“octocat”);

复制代码

service对象是动态代理对象Proxy.newProxyInstance(),当调用getCall()时会被 它拦截,然后调用自身的InvocationHandler#invoke(),得到最终的Call对象。

2、同步执行流程 repos.execute()

@Override public Response execute() throws IOException {

okhttp3.Call call;

synchronized (this) {

if (executed) throw new IllegalStateException(“Already executed.”);

executed = true;

if (creationFailure != null) {

if (creationFailure instanceof IOException) {

throw (IOException) creationFailure;

} else if (creationFailure instanceof RuntimeException) {

throw (RuntimeException) creationFailure;

} else {

throw (Error) creationFailure;

}

}

call = rawCall;

if (call == null) {

try {

// 创建一个OkHttp的Request对象请求

call = rawCall = createRawCall();

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

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

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

img

img

img

img

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

如果你觉得这些内容对你有帮助,可以扫码领取!!!!

总结

最后为了帮助大家深刻理解Android相关知识点的原理以及面试相关知识,这里放上相关的我搜集整理的14套腾讯、字节跳动、阿里、百度等2021面试真题解析,我把技术点整理成了视频和PDF(实际上比预期多花了不少精力),包知识脉络 + 诸多细节。

2020面试真题解析
腾讯面试真题解析

阿里巴巴面试真题解析

字节跳动面试真题解析
网上学习 Android的资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。希望这份系统化的技术体系对大家有一个方向参考。


《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》点击传送门,即可免费领取!

大厂,18年进入阿里一直到现在。**

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

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

[外链图片转存中…(img-eYkpWKkJ-1711224406974)]

[外链图片转存中…(img-dJbsA4LY-1711224406974)]

[外链图片转存中…(img-uwg20Aqt-1711224406975)]

[外链图片转存中…(img-jfBC5yID-1711224406975)]

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

如果你觉得这些内容对你有帮助,可以扫码领取!!!!

总结

最后为了帮助大家深刻理解Android相关知识点的原理以及面试相关知识,这里放上相关的我搜集整理的14套腾讯、字节跳动、阿里、百度等2021面试真题解析,我把技术点整理成了视频和PDF(实际上比预期多花了不少精力),包知识脉络 + 诸多细节。

[外链图片转存中…(img-7nne7k8n-1711224406975)]
[外链图片转存中…(img-oyXIH8tG-1711224406975)]

[外链图片转存中…(img-Dz0a6umZ-1711224406976)]

[外链图片转存中…(img-70KvBCBT-1711224406976)]
网上学习 Android的资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。希望这份系统化的技术体系对大家有一个方向参考。

[外链图片转存中…(img-MJztk78c-1711224406976)]
《Android学习笔记总结+移动架构视频+大厂面试真题+项目实战源码》点击传送门,即可免费领取!

http://www.tj-hxxt.cn/news/120350.html

相关文章:

  • 云主机怎么做网站今日百度搜索风云榜
  • 山东建设网站首页泰安短视频seo
  • 网站自动生成网页合肥头条今日头条新闻最新消息
  • 购物网站大全排名调查亚马逊关键词排名提升
  • 网站开发需要什么工具服装营销方式和手段
  • 网站如何做优化百度推广客服
  • 网站建设与维护新的体会抖音广告推广
  • 男生女生做羞羞事的网站媒体公关是做什么的
  • 网站上存储播放视频怎么做北京网络seo经理
  • 做响应式网站字体需要响应么网站快速排名优化报价
  • 合肥网站建设的公司网站关键词推广价格
  • 特卖网站怎么做百度seo排名优
  • 网站建设营销的技巧网络优化工具app手机版
  • 视频资源的网站怎么做百度投放
  • 日照时间网站seo思路
  • 用servlet做外卖网站app投放渠道有哪些
  • 卢湾品牌网站建设怎样推广自己的店铺啊
  • 做网站怎么签订协议全球网站流量排名查询
  • discuz 做的网站网络营销的类型有哪些
  • 个人怎么样做网站恶意点击推广神器
  • 桂林医院网站建设网络营销的优缺点
  • 网站建设锚点链接个人能接广告联盟吗
  • 崇信县门户网站官网国内免费顶级域名注册
  • 深圳网站建设 东莞网站建设班级优化大师使用指南
  • 自助建网站平台搜狗搜索引擎优化论文
  • wap网站下载外贸全网营销推广
  • 宁波网站建设服务商简述什么是seo
  • 文库网站怎么做seo爱链接购买链接
  • 中铁建设门户网登录赵伟班级优化大师手机版下载(免费)
  • 网站域名价格企业在线培训平台