public interface GitHubService {
@GET("/users/{user}/repos")
List<Repo> listRepos(@Path("user") String user);
}
RestAdapter restAdapter = new RestAdapter.Builder()
.setEndpoint("https://api.github.com")
.build();
GitHubService service = restAdapter.create(GitHubService.class);
List<Repo> repos = service.listRepos("octocat");
@GET("/group/{id}/users")
List<User> groupList(@Path("id") int groupId);
/** Make a GET request to a REST path relative to base URL. */
@Documented
@Target(METHOD)
@Retention(RUNTIME)
@RestMethod("GET")
public @interface GET {
String value();
}
@Documented
@Target(ANNOTATION_TYPE)
@Retention(RUNTIME)
public @interface RestMethod {
String value();
boolean hasBody() default false;
}
@Documented
@Target(METHOD)
@Retention(RUNTIME)
@RestMethod(value = "POST", hasBody = true)
public @interface POST {
String value();
}
RestAdapter restAdapter = new RestAdapter.Builder()
.setEndpoint("https://api.github.com")
.build();
GitHubService service = restAdapter.create(GitHubService.class);
public RestAdapter build() {
if (endpoint == null) {
throw new IllegalArgumentException("Endpoint may not be null.");
}
ensureSaneDefaults();
return new RestAdapter(endpoint, clientProvider, httpExecutor, callbackExecutor,
requestInterceptor, converter, profiler, errorHandler, log, logLevel);
}
private void ensureSaneDefaults() {
if (converter == null) { converter = Platform.get().defaultConverter(); }
if (clientProvider == null) { clientProvider = Platform.get().defaultClient(); }
if (httpExecutor == null) { httpExecutor = Platform.get().defaultHttpExecutor(); }
if (callbackExecutor == null) { callbackExecutor = Platform.get().defaultCallbackExecutor(); }
if (errorHandler == null) { errorHandler = ErrorHandler.DEFAULT; }
if (log == null) { log = Platform.get().defaultLog(); }
if (requestInterceptor == null) { requestInterceptor = RequestInterceptor.NONE; }
}
private static final Platform PLATFORM = findPlatform();
static final boolean HAS_RX_JAVA = hasRxJavaOnClasspath();
static Platform get() {
return PLATFORM;
}
private static Platform findPlatform() {
try {
Class.forName("android.os.Build");
if (Build.VERSION.SDK_INT != 0) {
return new Android();
}
} catch (ClassNotFoundException ignored) {
}
if (System.getProperty("com.google.appengine.runtime.version") != null) {
return new AppEngine();
}
return new Base();
}
abstract Converter defaultConverter(); // 默认的Converter,用于将请求结果转化成需要的数据,如GsonConverter将JSON请求结果用Gson解析成Java对象 abstract Client.Provider defaultClient(); // Http请求类,如果是AppEngine就使用`UrlFetchClient`,否则如果有OKHttp就使用OKHttp,如果是Android,2.3以后使用HttpURLConnection,2.3以前使用HttpClient abstract Executor defaultHttpExecutor(); // 用于执行Http请求的Executor abstract Executor defaultCallbackExecutor(); // Callback调用中用于执行Callback的Executor(可能是同步的) abstract RestAdapter.Log defaultLog(); // Log接口,用于输出Log
@Override Client.Provider defaultClient() {
final Client client;
if (hasOkHttpOnClasspath()) {
client = OkClientInstantiator.instantiate();
} else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.GINGERBREAD) {
client = new AndroidApacheClient();
} else {
client = new UrlConnectionClient();
}
return new Client.Provider() {
@Override public Client get() {
return client;
}
};
}
@Override Client.Provider defaultClient() {
final Client client;
if (hasOkHttpOnClasspath()) {
client = OkClientInstantiator.instantiate();
} else {
client = new UrlConnectionClient();
}
return new Client.Provider() {
@Override public Client get() {
return client;
}
};
}
@Override Client.Provider defaultClient() {
final UrlFetchClient client = new UrlFetchClient();
return new Client.Provider() {
@Override public Client get() {
return client;
}
};
}
@Override Executor defaultCallbackExecutor() {
return new Utils.SynchronousExecutor();
}
Platform.Android
@Override Executor defaultCallbackExecutor() {
return new MainThreadExecutor();
}
static class SynchronousExecutor implements Executor {
@Override public void execute(Runnable runnable) {
runnable.run();
}
}
public final class MainThreadExecutor implements Executor {
private final Handler handler = new Handler(Looper.getMainLooper());
@Override public void execute(Runnable r) {
handler.post(r);
}
}
public <T> T create(Class<T> service) {
Utils.validateServiceClass(service);
return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service },
new RestHandler(getMethodInfoCache(service)));
}
Map<Method, RestMethodInfo> getMethodInfoCache(Class<?> service) {
synchronized (serviceMethodInfoCache) {
Map<Method, RestMethodInfo> methodInfoCache = serviceMethodInfoCache.get(service);
if (methodInfoCache == null) {
methodInfoCache = new LinkedHashMap<Method, RestMethodInfo>();
serviceMethodInfoCache.put(service, methodInfoCache);
}
return methodInfoCache;
}
}
@Override public Object invoke(Object proxy, Method method, final Object[] args)
throws Throwable {
// If the method is a method from Object then defer to normal invocation.
if (method.getDeclaringClass() == Object.class) { // 1
return method.invoke(this, args);
}
// Load or create the details cache for the current method.
final RestMethodInfo methodInfo = getMethodInfo(methodDetailsCache, method); // 2
if (methodInfo.isSynchronous) { // 3
try {
return invokeRequest(requestInterceptor, methodInfo, args);
} catch (RetrofitError error) {
Throwable newError = errorHandler.handleError(error);
if (newError == null) {
throw new IllegalStateException("Error handler returned null for wrapped exception.",
error);
}
throw newError;
}
}
if (httpExecutor == null || callbackExecutor == null) {
throw new IllegalStateException("Asynchronous invocation requires calling setExecutors.");
}
// Apply the interceptor synchronously, recording the interception so we can replay it later.
// This way we still defer argument serialization to the background thread.
final RequestInterceptorTape interceptorTape = new RequestInterceptorTape();
requestInterceptor.intercept(interceptorTape); // 4
if (methodInfo.isObservable) { // 5
if (rxSupport == null) {
if (Platform.HAS_RX_JAVA) {
rxSupport = new RxSupport(httpExecutor, errorHandler);
} else {
throw new IllegalStateException("Observable method found but no RxJava on classpath");
}
}
return rxSupport.createRequestObservable(new Callable<ResponseWrapper>() {
@Override public ResponseWrapper call() throws Exception {
return (ResponseWrapper) invokeRequest(interceptorTape, methodInfo, args);
}
});
}
Callback<?> callback = (Callback<?>) args[args.length - 1]; // 6
httpExecutor.execute(new CallbackRunnable(callback, callbackExecutor, errorHandler) {
@Override public ResponseWrapper obtainResponse() {
return (ResponseWrapper) invokeRequest(interceptorTape, methodInfo, args);
}
});
return null; // Asynchronous methods should have return type of void.
}
static RestMethodInfo getMethodInfo(Map<Method, RestMethodInfo> cache, Method method) {
synchronized (cache) {
RestMethodInfo methodInfo = cache.get(method);
if (methodInfo == null) {
methodInfo = new RestMethodInfo(method);
cache.put(method, methodInfo);
}
return methodInfo;
}
private enum ResponseType {
VOID,
OBSERVABLE,
OBJECT
}
RestMethodInfo(Method method) {
this.method = method;
responseType = parseResponseType();
isSynchronous = (responseType == ResponseType.OBJECT);
isObservable = (responseType == ResponseType.OBSERVABLE);
}
synchronized void init() {
if (loaded) return;
parseMethodAnnotations();
parseParameters();
loaded = true;
}
for (Annotation methodAnnotation : method.getAnnotations()) {
Class<? extends Annotation> annotationType = methodAnnotation.annotationType();
RestMethod methodInfo = null;
// Look for a @RestMethod annotation on the parameter annotation indicating request method.
for (Annotation innerAnnotation : annotationType.getAnnotations()) {
if (RestMethod.class == innerAnnotation.annotationType()) {
methodInfo = (RestMethod) innerAnnotation;
break;
}
}
...
}
RequestBuilder requestBuilder = new RequestBuilder(serverUrl, methodInfo, converter); requestBuilder.setArguments(args); requestInterceptor.intercept(requestBuilder); Request request = requestBuilder.build();
/** Intercept every request before it is executed in order to add additional data. */
public interface RequestInterceptor {
/** Called for every request. Add data using methods on the supplied {@link RequestFacade}. */
void intercept(RequestFacade request);
interface RequestFacade {
void addHeader(String name, String value);
void addPathParam(String name, String value);
void addEncodedPathParam(String name, String value);
void addQueryParam(String name, String value);
void addEncodedQueryParam(String name, String value);
}
/** A {@link RequestInterceptor} which does no modification of requests. */
RequestInterceptor NONE = new RequestInterceptor() {
@Override public void intercept(RequestFacade request) {
// Do nothing.
}
};
}
// Apply the interceptor synchronously, recording the interception so we can replay it later. // This way we still defer argument serialization to the background thread. final RequestInterceptorTape interceptorTape = new RequestInterceptorTape(); requestInterceptor.intercept(interceptorTape);
Callback<?> callback = (Callback<?>) args[args.length - 1];
httpExecutor.execute(new CallbackRunnable(callback, callbackExecutor, errorHandler) {
@Override public ResponseWrapper obtainResponse() {
return (ResponseWrapper) invokeRequest(interceptorTape, methodInfo, args);
}
});
abstract class CallbackRunnable<T> implements Runnable {
private final Callback<T> callback;
private final Executor callbackExecutor;
private final ErrorHandler errorHandler;
CallbackRunnable(Callback<T> callback, Executor callbackExecutor, ErrorHandler errorHandler) {
this.callback = callback;
this.callbackExecutor = callbackExecutor;
this.errorHandler = errorHandler;
}
@SuppressWarnings("unchecked")
@Override public final void run() {
try {
final ResponseWrapper wrapper = obtainResponse();
callbackExecutor.execute(new Runnable() {
@Override public void run() {
callback.success((T) wrapper.responseBody, wrapper.response);
}
});
} catch (RetrofitError e) {
Throwable cause = errorHandler.handleError(e);
final RetrofitError handled = cause == e ? e : unexpectedError(e.getUrl(), cause);
callbackExecutor.execute(new Runnable() {
@Override public void run() {
callback.failure(handled);
}
});
}
}
public abstract ResponseWrapper obtainResponse();
}
/**
* Binary data with an associated mime type.
*
* @author Jake Wharton (jw@squareup.com)
*/
public interface TypedInput {
/** Returns the mime type. */
String mimeType();
/** Length in bytes. Returns {@code -1} if length is unknown. */
long length();
/**
* Read bytes as stream. Unless otherwise specified, this method may only be called once. It is
* the responsibility of the caller to close the stream.
*/
InputStream in() throws IOException;
}
/**
* Binary data with an associated mime type.
*
* @author Bob Lee (bob@squareup.com)
*/
public interface TypedOutput {
/** Original filename.
*
* Used only for multipart requests, may be null. */
String fileName();
/** Returns the mime type. */
String mimeType();
/** Length in bytes or -1 if unknown. */
long length();
/** Writes these bytes to the given output stream. */
void writeTo(OutputStream out) throws IOException;
}
TypedByteArray,内部数据是一个Byte数组
private final byte[] bytes;
@Override public long length() {
return bytes.length;
}
@Override public void writeTo(OutputStream out) throws IOException {
out.write(bytes);
}
@Override public InputStream in() throws IOException {
return new ByteArrayInputStream(bytes);
}
TypedString,继承自TypedByteArray,内部表示是一样的
public TypedString(String string) {
super("text/plain; charset=UTF-8", convertToBytes(string));
}
private static byte[] convertToBytes(String string) {
try {
return string.getBytes("UTF-8");
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
}
机械节能产品生产企业官网模板...
大气智能家居家具装修装饰类企业通用网站模板...
礼品公司网站模板
宽屏简约大气婚纱摄影影楼模板...
蓝白WAP手机综合医院类整站源码(独立后台)...苏ICP备2024110244号-2 苏公网安备32050702011978号 增值电信业务经营许可证编号:苏B2-20251499 | Copyright 2018 - 2025 源码网商城 (www.ymwmall.com) 版权所有