@Nullable和@Nonnull的使用
在编写方法时,入参、返回值,记得要用@Nullable和@Nonnull修饰,来达到提醒调用方的目的(kotlin应该不用)
泛型的大量使用
一个好的架构,一定是可以兼容各种数据类型,各种场景的,所以通过泛型可以很好的解决这些问题,所以泛型的使用是架构设计的核心
public interface TypeQualifierValidator<A extends Annotation> {
public @Nonnull
When forConstantValue(@Nonnull A annotation, Object value);
}
public final class Response<T> {
/** Create a synthetic successful response with {@code body} as the deserialized body. */
public static <T> Response<T> success(@Nullable T body) {
return success(
body,
new okhttp3.Response.Builder() //
.code(200)
.message("OK")
.protocol(Protocol.HTTP_1_1)
.request(new Request.Builder().url("http://localhost/").build())
.build());
}
}
public <T> T create(final Class<T> service) {
validateServiceInterface(service);
}
private void validateServiceInterface(Class<?> service) {
if (!service.isInterface()) {
throw new IllegalArgumentException("API declarations must be interfaces.");
}
Deque<Class<?>> check = new ArrayDeque<>(1);
}
final class
retrofit 源码中有大量的类都是使用final来修饰的
final修饰class有以下特点 :
- 当用final修饰一个类时,表明这个类不能被继承。也就是说,如果一个类你永远不会让他被继承,就可以用final进行修饰。
- 所以说,当开发时,如果写的类是非Activity、Fragment、View、Service等非android类时,应尽量考虑final class的情况
String类就是一个final类:
public final class String implements Serializable, Comparable<String>, CharSequence {
...
}
final 修饰方法时:
- 即父类的final方法是不能被子类所覆盖的,也就是说子类是不能够存在和父类一模一样的方法的
- 不能被重写
public class B extends A {
public void getName() {
}
}
class A {
public final void getName() {
}
}
当A类的getName是被final修饰时,如果B extends A ,那么不能重写getName方法,会直接报错:
getName()' cannot override 'getName()' in 'retrofit2.A'; overridden method is final
final 修饰变量时:
- final成员变量表示常量,只能被赋值一次,赋值后值不再改变。
static final class
public static final class Builder {}
build模式和工厂模式(工厂、抽象工厂)的使用
<? extends Annotation>和<?, ?>的使用
@Override
public Class<? extends Annotation> annotationType() {
return SkipCallbackExecutor.class;
}
abstract class(抽象类)的使用
abstract class ServiceMethod<T> {
static <T> ServiceMethod<T> parseAnnotations(Retrofit retrofit, Method method) {
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.");
}
return HttpServiceMethod.parseAnnotations(retrofit, method, requestFactory);
}
abstract @Nullable T invoke(Object[] args);
}
使用String字符串拼接时,要用StringBuilder
StringBuilder builder =
new StringBuilder("Could not locate call adapter for ").append(returnType).append(".\n");
if (skipPast != null) {
builder.append(" Skipped:");
for (int i = 0; i < start; i++) {
builder.append("\n * ").append(callAdapterFactories.get(i).getClass().getName());
}
builder.append('\n');
}
builder.append(" Tried:");
for (int i = start, count = callAdapterFactories.size(); i < count; i++) {
builder.append("\n * ").append(callAdapterFactories.get(i).getClass().getName());
}
throw new IllegalArgumentException(builder.toString());
StringBuilder效率高,线程不安全
StringBuffer效率低,线程安全
Objects.requireNonNull(type, "type == null");的使用
Objects.requireNonNull(type, "type == null");
Objects.requireNonNull(parameterAnnotations, "parameterAnnotations == null");
Objects.requireNonNull(methodAnnotations, "methodAnnotations == null");
底层(sdk组件)字段校验可以使用这样的方式,来避免调用方传一些错误字段,但是上层业务不能这样写,要处理异常而不是抛出
for循环中创建count对象
for (int i = start, count = converterFactories.size(); i < count; i++) {
Converter.Factory factory = converterFactories.get(i);
Converter<?, RequestBody> converter =
factory.requestBodyConverter(type, parameterAnnotations, methodAnnotations, this);
if (converter != null) {
//noinspection unchecked
return (Converter<T, RequestBody>) converter;
}
}
for循环中,使用count = converterFactories.size()的方法,直接创建了count对象
反射reflect中Type的意义和使用
/**
* Extract the upper bound of the generic parameter at {@code index} from {@code type}. For
* example, index 1 of {@code Map<String, ? extends Runnable>} returns {@code Runnable}.
*/
protected static Type getParameterUpperBound(int index, ParameterizedType type) {
return Utils.getParameterUpperBound(index, type);
}
/**
* Extract the raw class type from {@code type}. For example, the type representing {@code
* List<? extends Runnable>} returns {@code List.class}.
*/
protected static Class<?> getRawType(Type type) {
return Utils.getRawType(type);
}
List作为返回值,而不是ArrayList等
public List<Converter.Factory> converterFactories() {
return converterFactories;
}
动态代理的使用
public <T> T create(final Class<T> service) {
validateServiceInterface(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 @Nullable 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);
}
args = args != null ? args : emptyArgs;
return platform.isDefaultMethod(method)
? platform.invokeDefaultMethod(method, service, proxy, args)
: loadServiceMethod(method).invoke(args);
}
});
}
用线程池Executor而不是直接使用new Thread()
final @Nullable Executor callbackExecutor;
package-info.java的使用
@retrofit2.internal.EverythingIsNonNull
package retrofit2;
package-info.java是一个特殊的类,可以对整个包做操作。
retrofit中使用package-info.java为retrofit2包中的每一个类都添加了注释@retrofit2.internal.EverythingIsNonNull
kotlin中泛型、内联函数、扩展函数的用法:
inline fun <reified T> Retrofit.create(): T = create(T::class.java)