-
Notifications
You must be signed in to change notification settings - Fork 0
Home
wangchen edited this page Mar 22, 2017
·
53 revisions
[toc]
学习研究并最终实现基于Retrofit OkHttp 和RxJava Gson的Android 网络请求库
- 实现AuthToken的过期和二次自动获取机制 100%
- 实现基础的参数的自动加入 100%
- 实现参数的加密和签名 100%
- 支持GET POST 60%
- 实现一个NodeJs Server 模拟真实的服务器 100%
- 方便的支持Mock 40%
- 支持自定义Cache 100%
#尚未完成
conn = (HttpURLConnection) myUrl.openConnection();
public URLConnection openConnection() throws IOException {
return streamHandler.openConnection(this);
} /**
* Sets the stream handler factory for this VM.
*/
public static synchronized void setURLStreamHandlerFactory(URLStreamHandlerFactory factory) {
if (streamHandlerFactory != null) {
throw new Error("Factory already set");
}
streamHandlers.clear();
streamHandlerFactory = factory;
} void setupStreamHandler() {
// Check for a cached (previously looked up) handler for
// the requested protocol.
streamHandler = streamHandlers.get(protocol);
if (streamHandler != null) {
return;
}
if (protocol.equals("http")) {
try {
String name = "com.android.okhttp.HttpHandler";
streamHandler = (URLStreamHandler) Class.forName(name).newInstance();
} catch (Exception e) {
throw new AssertionError(e);
}
} else if (protocol.equals("https")) {
try {
String name = "com.android.okhttp.HttpsHandler";
streamHandler = (URLStreamHandler) Class.forName(name).newInstance();
} catch (Exception e) {
throw new AssertionError(e);
}
} else if (protocol.equals("jar")) {
streamHandler = new JarHandler();
}
if (streamHandler != null) {
streamHandlers.put(protocol, streamHandler);
}
}基于接口+注册

设置自己实现的 streamHandler + 反射 invoke 系统的handler
- Retrofit 是Square公司提供的高效的Http库,基于OK HTTP提供网络访问功能
- 将底层的代码都封装起来, 应用关注业务中的数据模型和操作方法
public interface IUserProfileService {
@FormUrlEncoded
@POST("/users/{user}/profile")
Call<ResultModel> updateUserProfile(@Field("userId") String userId, @Body UserProfile profile);
@Headers("Cache-Control: max-age=6400")
@GET("/users/{user}/profile")
Observable<Response<UserProfile>> getUserProfile(@Query("userId") String userId);
}
- API 使用
OkHttpClient.Builder clientBuilder = new OkHttpClient().newBuilder();
HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor();
httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
clientBuilder.addInterceptor(httpLoggingInterceptor);
clientBuilder.addInterceptor(new AddParamIterceptor());
CacheInterceptor cacheInterceptor = new CacheInterceptor(mContext);
clientBuilder.addInterceptor(new SignatureIterceptor()).addInterceptor(cacheInterceptor);
sOkHttpClient = clientBuilder.build();
cacheInterceptor.setCache(sOkHttpClient.cache());
sRetrofit = new Retrofit.Builder().client(sOkHttpClient)
.baseUrl(API)
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.addConverterFactory(GsonConverterFactory.create())
.build();
RetrofitUtil.getInstance(this)
.get(IUserProfileService.class)
.getUserProfile("498238400")
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Subscriber<Response<UserProfile>>() {
});
###内部原理
- 动态代理
public <T> T create(final Class<T> service) {
Utils.validateServiceInterface(service);
if (validateEagerly) {
eagerlyValidateMethods(service);
}
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, Object... args)
throws Throwable {
ServiceMethod serviceMethod = loadServiceMethod(method);
OkHttpCall okHttpCall = new OkHttpCall<>(serviceMethod, args);
return serviceMethod.callAdapter.adapt(okHttpCall);
}
});
}- CallAdapter
基于注册查找机制,returnType和CallAdapter对应 通过addCallAdapterFactory(RxJavaCallAdapterFactory.create()) 注册,在运行时通过returnType和CallAdapter 的关系找到
/*
* Copyright (C) 2015 Square, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package retrofit2;
import java.lang.annotation.Annotation;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
/**
* Adapts a {@link Call} into the type of {@code T}. Instances are created by {@linkplain Factory a
* factory} which is {@linkplain Retrofit.Builder#addCallAdapterFactory(Factory) installed} into
* the {@link Retrofit} instance.
*/
public interface CallAdapter<T> {
/**
* Returns the value type that this adapter uses when converting the HTTP response body to a Java
* object. For example, the response type for {@code Call<Repo>} is {@code Repo}. This type
* is used to prepare the {@code call} passed to {@code #adapt}.
* <p>
* Note: This is typically not the same type as the {@code returnType} provided to this call
* adapter's factory.
*/
Type responseType();
/**
* Returns an instance of {@code T} which delegates to {@code call}.
* <p>
* For example, given an instance for a hypothetical utility, {@code Async}, this instance would
* return a new {@code Async<R>} which invoked {@code call} when run.
* <pre><code>
* @Override
* public <R> Async<R> adapt(final Call<R> call) {
* return Async.create(new Callable<Response<R>>() {
* @Override
* public Response<R> call() throws Exception {
* return call.execute();
* }
* });
* }
* </code></pre>
*/
<R> T adapt(Call<R> call);
/**
* Creates {@link CallAdapter} instances based on the return type of {@linkplain
* Retrofit#create(Class) the service interface} methods.
*/
abstract class Factory {
/**
* Returns a call adapter for interface methods that return {@code returnType}, or null if it
* cannot be handled by this factory.
*/
public abstract CallAdapter<?> get(Type returnType, Annotation[] annotations,
Retrofit retrofit);
/**
* 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);
}
}
}- Converter 设计模式
###项目代码分析
依赖和参考项目
- https://github.com/alighters/AndroidDemos
- npm modules express body-parser
参考文献 http://expressjs.com/ https://github.com/alighters/AndroidDemos