/**
* Create the {@link Retrofit} instance using the configured values.
*
* Note: If neither {@link #client} nor {@link #callFactory} is called a default {@link
* OkHttpClient} will be created and used.
* 通过配置创建Retrofit实例,如果没有给Retrofit设置client或者callFactory,
* 那么会创建并使用默认的OkHttpClient
*/
public Retrofit build() {
// 1.1 检验baseUrl是否为空
if (baseUrl == null) {
throw new IllegalStateException("Base URL required.");
}
// 1.2 获取执行网络请求调用call的callFactory,如果没有则会使用默认的OkHttpClient
okhttp3.Call.Factory callFactory = this.callFactory;
if (callFactory == null) {
callFactory = new OkHttpClient();
}
// 1.3 获取默认的回调执行器,没有设置会使用默认平台的执行器,主要用于执行call中返回的execute,request,enqueue等方法
Executor callbackExecutor = this.callbackExecutor;
if (callbackExecutor == null) {
callbackExecutor = platform.defaultCallbackExecutor();
}
// 1.4 制作适配器的防御副本并添加默认的呼叫适配器。
// Make a defensive copy of the adapters and add the default Call adapter.
List adapterFactories = new ArrayList<>(this.adapterFactories);
adapterFactories.add(platform.defaultCallAdapterFactory(callbackExecutor));
// 1.5 制作转换器的防御副本
// Make a defensive copy of the converters.
List converterFactories = new ArrayList<>(this.converterFactories);
// 1.6 使用上述参数创建retrofit对象
return new Retrofit(callFactory, baseUrl, converterFactories, adapterFactories,
callbackExecutor, validateEagerly);
}
二、retrofit创建接口实例
下面我们先分析一下create中进行的操作
@SuppressWarnings("unchecked") // Single-interface proxy creation guarded by parameter safety.
public T create(final Class service) {
// 2.1 校验传入的参数是否是interface类型
Utils.validateServiceInterface(service);
// 这里validateEagerly默认初始化为false
if (validateEagerly) {
eagerlyValidateMethods(service);
}
// 2.2 使用动态代理,解析接口方法的注解和申明字段,并创建传入接口的实例
return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class>[] { service },
new InvocationHandler() {
private final Platform platform = Platform.get();
@Override public Object invoke(Object proxy, Method method, @Nullable Object[] args)
throws Throwable {
// 如果是继承自父类Object的方法
// 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);
}
// 步骤一 :Service接口上申明的方法, 这里会解析方法的注解,参数和返回值,并根据相关的信息找到对应的转换器Converter和CallAdapter,这些信息都将保存在ServiceMethod中,最后将方法参数和ServiceMethod存入OkHttpCall中
ServiceMethod
ServiceMethod, ?> loadServiceMethod(Method method) {
// 从缓存中查看是否解析过该方法
ServiceMethod, ?> result = serviceMethodCache.get(method);
if (result != null) return result;
// 缓存中没有的话,同步执行解析方法,并将解析接过存入缓存中
synchronized (serviceMethodCache) {
result = serviceMethodCache.get(method);
if (result == null) {
// Builder构造方法,获取了方法的注解,参数类型,参数注解
result = new ServiceMethod.Builder<>(this, method).build();
serviceMethodCache.put(method, result);
}
}
return result;
}
==ServiceMethod==是ServiceMethod中核心的方法,需要详细的分析
public ServiceMethod build() {
// 1.创建出调用Adapter,并获取响应类型
callAdapter = createCallAdapter();
responseType = callAdapter.responseType();
// 判断响应类型是否合法
if (responseType == Response.class || responseType == okhttp3.Response.class) {
throw methodError("'"
+ Utils.getRawType(responseType).getName()
+ "' is not a valid response body type. Did you mean ResponseBody?");
}
// 2. 根据初始化Retrofit时候设置的转化器和默认的转化器BuildInConverter,创建对应方法响应的converter,当有多个符合条件的转化器时,会选择List中第一个符合条件的converter
responseConverter = createResponseConverter();
// 3. 转化接口方法注解,
for (Annotation annotation : methodAnnotations) {
parseMethodAnnotation(annotation);
}
......
// 4. 解析方法参数注解,并存储在ParameterHandler中
int parameterCount = parameterAnnotationsArray.length;
parameterHandlers = new ParameterHandler>[parameterCount];
for (int p = 0; p < parameterCount; p++) {
Type parameterType = parameterTypes[p];
if (Utils.hasUnresolvableType(parameterType)) {
throw parameterError(p, "Parameter type must not include a type variable or wildcard: %s",
parameterType);
}
Annotation[] parameterAnnotations = parameterAnnotationsArray[p];
if (parameterAnnotations == null) {
throw parameterError(p, "No Retrofit annotation found.");
}
parameterHandlers[p] = parseParameter(p, parameterType, parameterAnnotations);
}
......
// 最终把Builder中的数据存入到ServiceMethod中
return new ServiceMethod<>(this);
}
--分组取最大最小常用sql--测试环境if OBJECT_ID('tb') is not null drop table tb;gocreate table tb( col1 int, col2 int, Fcount int)insert into tbselect 11,20,1 union allselect 11,22,1 union allselect 1
一、函数的使用
1.1、定义函数变量
var vName = funcation(params){
}
1.2、函数的调用
函数变量的调用: vName(params);
函数定义时自发调用:(function(params){})(params);
1.3、函数中变量赋值
var a = 'a';
var ff
Mac mini 型号: MC270CH-A RMB:5,688
Apple 对windows的产品支持不好,有以下问题:
1.装完了xp,发现机身很热虽然没有运行任何程序!貌似显卡跑游戏发热一样,按照那样的发热量,那部机子损耗很大,使用寿命受到严重的影响!
2.反观安装了Mac os的展示机,发热量很小,运行了1天温度也没有那么高
&nbs
Follow up for "Search in Rotated Sorted Array":What if duplicates are allowed?
Would this affect the run-time complexity? How and why?
Write a function to determine if a given ta