Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Copyright (C) 2012 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 static java.util.Collections.unmodifiableList;
import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Proxy;
import java.lang.reflect.Type;
import java.net.URL;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Deque;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executor;
import javax.annotation.Nullable;
import okhttp3.HttpUrl;
import okhttp3.OkHttpClient;
import okhttp3.RequestBody;
import okhttp3.ResponseBody;
import retrofit2.http.GET;
import retrofit2.http.HTTP;
import retrofit2.http.Header;
import retrofit2.http.Url;
/**
* Retrofit adapts a Java interface to HTTP calls by using annotations on the declared methods to
* define how requests are made. Create instances using {@linkplain Builder the builder} and pass
* your interface to {@link #create} to generate an implementation.
*
*
For example,
*
*
* Retrofit retrofit = new Retrofit.Builder()
* .baseUrl("https://api.example.com/")
* .addConverterFactory(GsonConverterFactory.create())
* .build();
*
* MyApi api = retrofit.create(MyApi.class);
* Response<User> user = api.getUser().execute();
*
*
* @author Bob Lee ([email protected])
* @author Jake Wharton ([email protected])
*/
public final class Retrofit {
/**
* Method associations in this map will be in one of three states, and may only progress forward
* to higher-numbered states.
*
*
No value - no one has started or completed parsing annotations for the method.
*
Lock object - a thread has started parsing annotations on the method. Once the lock is
* available the map will have been updated with the parsed model.
*
{@code ServiceMethod} - annotations for the method have been fully parsed.
*
* This map should only be accessed through {@link #loadServiceMethod} which contains the state
* transition logic.
*/
private final ConcurrentHashMap serviceMethodCache = new ConcurrentHashMap<>();
final okhttp3.Call.Factory callFactory;
final HttpUrl baseUrl;
final List converterFactories;
final int defaultConverterFactoriesSize;
final List callAdapterFactories;
final int defaultCallAdapterFactoriesSize;
final @Nullable Executor callbackExecutor;
final boolean validateEagerly;
Retrofit(
okhttp3.Call.Factory callFactory,
HttpUrl baseUrl,
List converterFactories,
int defaultConverterFactoriesSize,
List callAdapterFactories,
int defaultCallAdapterFactoriesSize,
@Nullable Executor callbackExecutor,
boolean validateEagerly) {
this.callFactory = callFactory;
this.baseUrl = baseUrl;
this.converterFactories = converterFactories; // Copy+unmodifiable at call site.
this.defaultConverterFactoriesSize = defaultConverterFactoriesSize;
this.callAdapterFactories = callAdapterFactories; // Copy+unmodifiable at call site.
this.defaultCallAdapterFactoriesSize = defaultCallAdapterFactoriesSize;
this.callbackExecutor = callbackExecutor;
this.validateEagerly = validateEagerly;
}
/**
* Create an implementation of the API endpoints defined by the {@code service} interface.
*
*
The relative path for a given method is obtained from an annotation on the method describing
* the request type. The built-in methods are {@link retrofit2.http.GET GET}, {@link
* retrofit2.http.PUT PUT}, {@link retrofit2.http.POST POST}, {@link retrofit2.http.PATCH PATCH},
* {@link retrofit2.http.HEAD HEAD}, {@link retrofit2.http.DELETE DELETE} and {@link
* retrofit2.http.OPTIONS OPTIONS}. You can use a custom HTTP method with {@link HTTP @HTTP}. For
* a dynamic URL, omit the path on the annotation and annotate the first parameter with {@link
* Url @Url}.
*
*
Method parameters can be used to replace parts of the URL by annotating them with {@link
* retrofit2.http.Path @Path}. Replacement sections are denoted by an identifier surrounded by
* curly braces (e.g., "{foo}"). To add items to the query string of a URL use {@link
* retrofit2.http.Query @Query}.
*
*
The body of a request is denoted by the {@link retrofit2.http.Body @Body} annotation. The
* object will be converted to request representation by one of the {@link Converter.Factory}
* instances. A {@link RequestBody} can also be used for a raw representation.
*
*
Alternative request body formats are supported by method annotations and corresponding
* parameter annotations:
*
*
*
{@link retrofit2.http.FormUrlEncoded @FormUrlEncoded} - Form-encoded data with key-value
* pairs specified by the {@link retrofit2.http.Field @Field} parameter annotation.
*
{@link retrofit2.http.Multipart @Multipart} - RFC 2388-compliant multipart data with
* parts specified by the {@link retrofit2.http.Part @Part} parameter annotation.
*
*
*
Additional static headers can be added for an endpoint using the {@link
* retrofit2.http.Headers @Headers} method annotation. For per-request control over a header
* annotate a parameter with {@link Header @Header}.
*
*
By default, methods return a {@link Call} which represents the HTTP request. The generic
* parameter of the call is the response body type and will be converted by one of the {@link
* Converter.Factory} instances. {@link ResponseBody} can also be used for a raw representation.
* {@link Void} can be used if you do not care about the body contents.
*
*
For example:
*
*
* public interface CategoryService {
* @POST("category/{cat}/")
* Call<List<Item>> categoryList(@Path("cat") String a, @Query("page") int b);
* }
*
*/
@SuppressWarnings("unchecked") // Single-interface proxy creation guarded by parameter safety.
public T create(final Class service) {
validateServiceInterface(service);
return (T)
Proxy.newProxyInstance(
service.getClassLoader(),
new Class>[] {service},
new InvocationHandler() {
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;
Reflection reflection = Platform.reflection;
return reflection.isDefaultMethod(method)
? reflection.invokeDefaultMethod(method, service, proxy, args)
: loadServiceMethod(service, method).invoke(proxy, args);
}
});
}
private void validateServiceInterface(Class> service) {
if (!service.isInterface()) {
throw new IllegalArgumentException("API declarations must be interfaces.");
}
Deque> check = new ArrayDeque<>(1);
check.add(service);
while (!check.isEmpty()) {
Class> candidate = check.removeFirst();
if (candidate.getTypeParameters().length != 0) {
StringBuilder message =
new StringBuilder("Type parameters are unsupported on ").append(candidate.getName());
if (candidate != service) {
message.append(" which is an interface of ").append(service.getName());
}
throw new IllegalArgumentException(message.toString());
}
Collections.addAll(check, candidate.getInterfaces());
}
if (validateEagerly) {
Reflection reflection = Platform.reflection;
for (Method method : service.getDeclaredMethods()) {
if (!reflection.isDefaultMethod(method)
&& !Modifier.isStatic(method.getModifiers())
&& !method.isSynthetic()) {
loadServiceMethod(service, method);
}
}
}
}
ServiceMethod> loadServiceMethod(Class> service, Method method) {
while (true) {
// Note: Once we are minSdk 24 this whole method can be replaced by computeIfAbsent.
Object lookup = serviceMethodCache.get(method);
if (lookup instanceof ServiceMethod>) {
// Happy path: method is already parsed into the model.
return (ServiceMethod>) lookup;
}
if (lookup == null) {
// Map does not contain any value. Try to put in a lock for this method. We MUST synchronize
// on the lock before it is visible to others via the map to signal we are doing the work.
Object lock = new Object();
synchronized (lock) {
lookup = serviceMethodCache.putIfAbsent(method, lock);
if (lookup == null) {
// On successful lock insertion, perform the work and update the map before releasing.
// Other threads may be waiting on lock now and will expect the parsed model.
ServiceMethod