[JAVA] J'ai étudié le traitement interne de Retrofit

Aperçu

Il n'y a pas longtemps, j'ai créé un article sur la façon d'exécuter l'API Web (Hatena Bookmark Entry Information Acquisition API) en utilisant Retrofit + Gson.

J'ai obtenu le code source de Retrofit de github et j'ai étudié la méthode d'implémentation qui permet le traitement d'accès à l'API Web simplement en créant une interface.

En conséquence, j'ai constaté que j'utilisais l'API Proxy of Reflect.

Comme le traitement est redondant / la visibilité se détériore, il se peut qu'il n'y ait pas beaucoup de cas où Proxy est utilisé dans la mise en œuvre de l'application, mais j'ai pensé que c'était une utilisation intéressante.

Qu'est-ce que la modernisation

Retrofit est une application Android (Java), une bibliothèque open source pour un accès facile aux API Web (données json). À utiliser en combinaison avec les bibliothèques de conversion de données json (gson, jackson, etc.).

Traitement de l'exécution de l'API Web par Retrofit

Le processus d'exécution de l'API Web est implémenté par la procédure suivante.

Interface API implémentée

Tout d'abord, implémentez l'interface pour l'API. L'interface suivante est un exemple de l'API d'acquisition d'informations d'entrée de signets Hatena.

// HatenaApiInterface.java
public interface HatenaApiInterface {
    String END_POINT = "http://b.hatena.ne.jp";
    String TARGET_URL = "http://b.hatena.ne.jp/ctop/it";

    //API d'acquisition d'informations d'entrée de signets Hatena
    // http://developer.hatena.ne.jp/ja/documents/bookmark/apis/getinfo
    @GET("/entry/jsonlite/")
    Call<BookmarkEntry> getBookmarkEntry(@Query("url") String target);

}

L'URL suivante est l'URL de l'API d'acquisition d'informations d'entrée de signets Hatena (GET) liée à la technologie. Où url est un argument qui indique la catégorie. Veuillez consulter ici pour les spécifications de l'API d'acquisition d'informations d'entrée de signets Hatena.

http://b.hatena.ne.jp/entry/jsonlite/?url=http%3A%2F%2Fb.hatena.ne.jp%2Fctop%2Fit

Décrivez les informations qui peuvent générer cette URL dans l'interface.

point final

Le point de terminaison est l'URL racine de l'API Web. Utilisé lors de la création d'une instance de Retrofit.

Méthode

Le nom de la méthode est arbitraire. L'annotation (@GET) indique que vous utilisez la méthode GET et que le chemin relatif de l'API Web est `` / entry / jsonlite / ''. En outre, l'annotation (@Query) est ajoutée en tant que chaîne de requête ci-dessous?

Implémentation du traitement d'accès aux API Web

Suivez les étapes ci-dessous pour accéder à l'API Web. (Principal) Mettre en œuvre dans l'activité, etc.

  1. Créer une instance Retrofit
  2. Créez une interface pour l'accès à l'API Web
  3. Exécution de l'API Web
 	//Création d'instances de modernisation
    Retrofit retrofit = new Retrofit.Builder()
            .baseUrl(HatenaApiInterface.END_POINT)
            .addConverterFactory(GsonConverterFactory.create())
            .build();

    //Création d'une interface pour l'accès à l'API Web
    mApiInterface = retrofit.create(HatenaApiInterface.class);
    
    //Instance d'exécution de l'API Web(interface)Obtenir.
    Call<BookmarkEntry> call = mApiInterface.getBookmarkEntry(targetUrl);
    
    //Exécutez l'API Web
    //Le résultat du traitement est notifié par l'appel de rappel
    call.enqueue(new Callback<BookmarkEntry>() {
        @Override
        public void onResponse(Call<BookmarkEntry> call, Response<BookmarkEntry> response) {
            //Décrit le processus lorsque l'accès à l'API Web réussit
            }

        @Override
        public void onFailure(Call<BookmarkEntry> call, Throwable t) {
            //Décrit le traitement en cas d'échec de l'accès à l'API Web
        }
    });

Explication du traitement interne

Vous trouverez ci-dessous la source de Retrofit.create.

InvocationHandler est créé et renvoyé à l'aide de l'API Proxy of Reflect. Lorsque vous exécutez getBookmarkEntry de l'interface (instance) acquise, la méthode invoke est exécutée. Le nom de la méthode getBookmarkEntry est stocké dans l'argument Method et la chaîne targetUrl est stockée dans l'argument args.

Utilisez loadServiceMethod pour obtenir les informations d'accès à l'API Web associées à cette méthode. Ajoutez une autre classe d'appel okHttp et renvoyez la classe Adapter. Définissez ceci sur une variable de type Call call```

Exécutez ensuite la méthode enqueque pour effectuer un appel d'API Web. Le résultat peut être obtenu en rappelant l'argument.

  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 {
            // 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);
            }
            ServiceMethod<Object, Object> serviceMethod =
                (ServiceMethod<Object, Object>) loadServiceMethod(method);
            OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
            return serviceMethod.callAdapter.adapt(okHttpCall);
          }
        });
  }

Comment utiliser Proxy (exemple)

Explique comment utiliser l'API Proxy of Reflect. Voir c'est croire. Créez TestInterface et TestProxy et essayez d'exécuter TestProxy. Vous pouvez bien voir l'explication ci-dessus.

Pour savoir comment utiliser Proxy, je me suis référé à ici.

$ java TestProxy
$ cat TestInterface.java
public interface TestInterface {
	public void doSomething();
}

$ cat TestProxy.java
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

public class TestProxy {
	private Object proxy;
	private TestProxy(Class<TestInterface> clazz) {
		this.proxy = Proxy.newProxyInstance(clazz.getClassLoader(),
				new Class[] { clazz },
				new InvocationHandler() {
					public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
					    //Informations sur la méthode de sortie
						System.out.println("method: " + method);
						return null;
					}
		});
	}
	
	public static TestInterface createProxy(Class<TestInterface> clazz) {
		TestProxy obj = new TestProxy(clazz);
		return clazz.cast(obj.proxy);
	}
	
	public static void main(String[] args) {
		TestInterface someInterface = TestProxy.createProxy(TestInterface.class);
		someInterface.doSomething();
	}
}

référence

Recommended Posts

J'ai étudié le traitement interne de Retrofit
J'ai enquêté sur l'instance englobante.
J'ai lu la source de ArrayList que j'ai lu
J'ai lu la source d'Integer
J'ai lu la source de Long
J'ai lu la source de Short
J'ai lu la source de Byte
Ordre de traitement dans le programme
J'ai lu la source de String
J'ai étudié le mécanisme d'attr_accessor (* Hoge :: ATTRIBUTES) que je vois parfois
Je veux comprendre le flux des paramètres de demande de traitement Spring
[jour: 5] J'ai résumé les bases de Java
[Spring Boot] J'ai étudié comment implémenter le post-traitement de la demande reçue.
Calcul à rebours de la transition de la graine interne de Random
J'ai vérifié la partie de java.net.URL # getPath
J'ai compris les bases de la saisie de caractères
J'ai comparé les caractéristiques de Java et .NET
Je veux var_dump le contenu de l'intention
J'ai essayé d'utiliser le profileur d'IntelliJ IDEA
J'ai vérifié le nombre de taxis avec Ruby
Essayez Progate Free Edition [Java I]
J'ai examiné le cycle de vie de l'extension de JUnit Jupiter
J'ai essayé d'utiliser la fonction Server Push de Servlet 4.0
J'étais accro au record du modèle associé
J'ai vu la liste du développement Android collectivement
[Chacun, carte ...] J'ai comparé le traitement du tableau ce soir [ruby]
05. J'ai essayé de supprimer la source de Spring Boot
J'ai essayé de réduire la capacité de Spring Boot
J'ai essayé le nouveau profileur de fonctionnalités d'IntelliJ IDEA 2019.2.
Je veux connaître la réponse de l'application Janken
Surveillez l'état interne des programmes Java avec Kubernetes
Traitement d'image: structure de base de l'image lue par le programme
Je souhaite afficher le nom de l'affiche du commentaire
J'ai résumé le format d'affichage de la réponse JSON de Rails
J'ai écrit un diagramme de séquence de l'exemple j.u.c.Flow
J'ai résumé les types et les bases des exceptions Java
Je suis parfaitement conscient de la commodité de graphql-code-generator partie 2
Je ne peux pas sortir de l'écran de la console Rails db
Contrôlez le flux de traitement Spring Batch avec JavaConfig.
Je veux retourner la position de défilement de UITableView!
Le monde de Clara-Rules (2)
Jugement du calendrier
Le monde de Clara-Rules (4)
Le monde de Clara-Rules (1)
Le monde de Clara-Rules (3)
J'ai étudié l'automatisation des tests
Le monde de Clara-Rules (5)
L'idée du tri rapide
L'idée de jQuery
J'ai créé le côté serveur du jeu de cartes en ligne ①