Las devoluciones de llamada se definen en Wikipedia como:
En la programación de computadoras, una función de devolución de llamada se refiere a una referencia a una determinada pieza de código ejecutable que se pasa a otro código a través de parámetros de función.
El propósito es permitir que el código subyacente llame a subrutinas definidas en el nivel superior.
Por ejemplo, puede ser más claro: tomar el uso de una modernización para las solicitudes de red en Android como ejemplo, este es un ejemplo de devoluciones de llamada asincrónicas.
Después de iniciar una solicitud de red, la aplicación puede continuar otras cosas. El resultado de la solicitud de red generalmente se obtiene a través de los dos métodos de respuesta y onfailure. Eche un vistazo al código en la parte relevante:
call.enqueue (nueva devolución de llamada <ShydyBean> () {@Override public void onResponse (call <hiphysBean> call, respuesta <hipsyBean> respuesta) {HistoryBean HB = Response.Body (); if (Hb == NULL) return; showText.append (hb.iserror () + "); para (HistoryBean.ResultSbean RB: RB: RB: RB: RB: RB: hb.getResults ()) {showText.append (rb.gettitle () + "/n");Ignora los genéricos en la devolución de llamada anterior. De acuerdo con la definición en Wikipedia, todo el código en una clase interna anónima puede considerarse como una referencia a un cierto código ejecutable que se pasa a otros códigos . Los dos métodos On -Response y Onfailure son los métodos de devolución de llamada. El código subyacente es la parte de solicitud de red sin cambios que se ha escrito, y la subrutina definida por el nivel superior es la devolución de llamada. Debido a que la implementación específica se entrega al usuario, tiene una alta flexibilidad. Lo anterior está relacionado a través del método Enqueue (devolución de llamada).
Pasos de método de devolución de llamada
La devolución de llamada mencionada anteriormente es un concepto muy común. Si lo pone en la escritura del programa, puede decir:
En la clase A, se llama a un método C en la clase B, y luego en la clase B, el método D en la clase A se llama en reversa. D es el método de devolución de llamada. La clase B es el código subyacente, y la clase A es el código de alto nivel.
Entonces, a través de la explicación anterior, podemos inferir algo. Para representar la universalidad del método D, utilizamos el formulario de interfaz para hacer que el método D se llame un método de interfaz. Si la Clase B quiere llamar al Método D en la Clase A, la Clase A debe implementar esta interfaz. De esta manera, dependiendo de la implementación, habrá polimorfismo, lo que hace que el método sea flexible.
Si la Clase A quiere llamar a un Método C en la Clase B, entonces la Clase A debe contener una referencia a B, de lo contrario no se llamará. Este paso se llama interfaz de devolución de llamada de registro. Entonces, cómo implementar el método de llamada inversa D en la clase A en la clase B, directamente a través del método anterior C. El método C en la clase B acepta un parámetro de tipo de interfaz. Luego, solo en el método C, debe usar los parámetros de esta interfaz tipo para llamar al método D en la clase B, que a su vez llama el método D en la clase A. Este paso se llama llamar a la interfaz de devolución de llamada.
Esto también implementa que en el método C de la clase B, el método D en la Clase A debe llamarse a la inversa, que es la devolución de llamada. A llama a B para sintonizar directamente, lo que puede considerarse utilizando la API subyacente para el código de alto nivel. A menudo escribimos programas como este. B llama a A para devolver la llamada, y la API subyacente requiere un código de alto nivel para ejecutar.
Finalmente, resumamos los pasos del método de devolución de llamada:
Ejemplo de devolución de llamada
Tomemos un hijo jugando y esperando que su madre prepare la comida y notifique a su hijo que venga a comer como ejemplo, y siga los pasos anteriores para escribir una devolución de llamada;
En el ejemplo anterior, es obvio que el hijo debe implementar la interfaz de devolución de llamada y la madre debe llamar a la interfaz de devolución de llamada. Por lo tanto, primero definimos una interfaz de devolución de llamada y luego dejamos que nuestro hijo implemente esta interfaz de devolución de llamada.
El código es el siguiente:
devolución de llamada de interfaz pública {void eat ();} El hijo de clase pública implementa la devolución de llamada {Mamá privada mamá; // La clase A tiene una referencia a la clase B public void setMom (mamá mamá) {this.mom = mamá; } @Override public void eat () {System.out.println ("Estoy aquí para comer"); } public void askMom () {// llamando a un método con parámetros de interfaz a través de una referencia a la clase B. System.out.println ("¿Se ha cocinado la comida?"); System.out.println ("No hecho, estoy jugando el juego"); nuevo hilo (() -> Mom.docook (son.this)). Start (); System.out.println ("Jugando el juego ..."); }}Entonces también necesitamos definir una clase de madre, que contiene un método DOCOOK con parámetros de interfaz
public class MOM {// llama al método de devolución de llamada utilizando parámetros de interfaz en un método que contiene parámetros de interfaz public void docook (llamada de devolución de llamada) {new Thread (new runnable () {@Override public void run () {try {System.out.println ("Cooking ..."); Thread.slele (5000); Callback.eat.eat.;} Catched Et. E.PrintStackTrace (); }}Pasamos una clase de prueba:
Prueba de clase pública {public static void main (String [] args) {Mom Mom = New Mom (); Hijo hijo = nuevo hijo (); Son.SetMom (mamá); hijo.askmom (); }}Este ejemplo es un ejemplo típico de devolución de llamada. La clase SON implementa el método de devolución de llamada de la interfaz. Llama a Dookook en la clase MOM a través del método AskMom para registrar la interfaz de devolución de llamada, que es equivalente a llamar al Código C de Clase B en la Clase A. DoCook en la clase MOM Llamadas de un lado a otro la clase Eat in the Son para decir los resultados en la clase SON.
De esta manera, implementamos una devolución de llamada simple y definida.
Exploración adicional de ejemplos de devolución de llamada
Veamos principalmente el Código de la clase SON:
El hijo de clase pública implementa la devolución de llamada {public Mom Mom; hijo público (mamá mamá) {this.mom = mamá; } public void askMom () {System.out.println ("¿Se ha cocinado la comida?"); System.out.println ("No lo he hecho bien, he jugado el juego"); nuevo hilo (() -> Mom.docook (son.this)). Start (); System.out.println ("He jugado el juego ..."); } @Override public void eat () {System.out.println ("Está bien, estoy aquí para comer"); }}En esta clase, además de emitir algunas declaraciones, las partes realmente útiles son mamá. Por lo tanto, podemos abreviar esta devolución de llamada a través de la forma de clase interna anónima. El código es el siguiente:
public class CallbackTest {public static void main (String [] args) {Mom Mom = New Mom (); New Thread (() -> Mom.docook (() -> System.out.println ("He comido ..."))). Start (); }}Cancele la clase SON e implemente directamente el método EAT a través de la clase interna anónima en el método principal. De hecho, las clases internas anónimas son la encarnación de las devoluciones de llamada.
Devoluciones de llamada asincrónicas y devoluciones de llamada sincrónicas
Devolución de llamada: un método C de llamadas en la clase B, y luego llama al método D en la clase A a través de objetos de clase A en el método C.
Hablemos sobre asincrónicos y sincronización, primero hablemos sobre el concepto de sincronización.
sincrónico
La sincronización significa que al llamar a un método, si la llamada de método anterior no se ejecuta, no se puede realizar una nueva llamada de método. En otras palabras, las cosas deben hacerse una por una, y solo puedes hacer la siguiente tras otra.
asincrónico
La asíncrona es relativa a la sincronización, no necesita esperar hasta que se termine la llamada del método anterior antes de llamar a un nuevo método. Por lo tanto, en las llamadas de método asíncrono, se necesita un método para notificar al usuario del resultado de la llamada del método.
Implementar métodos asíncronos
La forma más común de implementar asíncrono en Java es dejar que el método que desea ejecutar asíncronamente en un nuevo hilo.
Encontraremos que se necesita un método en una llamada de método asíncrono para notificar al resultado de la llamada del usuario. Según lo anterior, encontraremos que el método de devolución de llamada es adecuado para hacer esto y notificaremos al usuario del resultado de la llamada a través del método de devolución de llamada.
La devolución de llamada asincrónica se realiza en un nuevo hilo cuando llama un método C de B.
El ejemplo anterior de la madre que notifica a su hijo para la cena es un ejemplo de una devolución de llamada asincrónica. En un nuevo hilo, se llama al método Dookek y el valor de retorno finalmente se acepta a través de EAT. Por supuesto, después de usar la optimización de Lamdba, la esencia es la misma.
La devolución de llamada sincrónica significa que un método B de llamadas B no en un nuevo hilo. Al ejecutar este método C, no podemos hacer nada y solo podemos esperar a que se complete.
Ejemplos de devoluciones de llamada sincrónicas y devoluciones de llamada asincrónicas
Veamos un ejemplo de una devolución de llamada sincrónica en Android:
Button.SetOnClickListener (new View.OnClickListener () {@Override public void onClick (ver v) {log.i ("botón", "hizo clic");}});El botón registra la función de devolución de llamada a través de SetOnClickListener y, como se escribe anteriormente, pasa la referencia de la interfaz en forma de una clase interna anónima. Dado que el botón llama a SetOnClickListener sin crear un nuevo hilo, esta es una devolución de llamada sincrónica.
La devolución de llamada asíncrona es el ejemplo del que hablamos al principio:
call.enqueue (nueva devolución de llamada <ShydyBean> () {@Override public void onResponse (call <hiphysBean> call, respuesta <hipsyBean> respuesta) {HistoryBean HB = Response.Body (); if (Hb == NULL) return; showText.append (hb.iserror () + "); para (HistoryBean.ResultSbean RB: RB: RB: RB: RB: RB: hb.getResults ()) {showText.append (rb.gettitle () + "/n");Este método de Enqueue es un método asincrónico para solicitar datos de red remotos. Cuando se implementa internamente, se ejecuta a través de un nuevo hilo.
A través de estos dos ejemplos, podemos ver que el uso de devoluciones de llamada sincrónicas y devoluciones de llamada asincrónicas en realidad está diseñado de acuerdo con diferentes necesidades. No se puede decir que uno reemplace al otro. Por ejemplo, en el evento de clic del botón anterior, si se trata de una devolución de llamada asíncrona, el efecto de clic no aparece inmediatamente después de que el usuario haga clic en el botón y el usuario no realizará otras operaciones, se sentirá extraño. Las devoluciones de llamada asíncronas para las solicitudes de red, debido a que el recurso solicitado puede no existir, la conexión de red es inestable y otras razones, el usuario no está claro sobre la ejecución del método, por lo que utilizará náuseas asincrónicas, iniciará la llamada del método y hará otras cosas, y luego esperará la notificación de devolución de llamada.
Aplicación del método de devolución de llamada en la comunicación
Los métodos de devolución de llamada mencionados anteriormente, excepto las devoluciones de llamada del marco de solicitud de red, todos no tienen parámetros. Echemos un vistazo a agregar parámetros al método de devolución de llamada para implementar algunos problemas de comunicación.
Si queremos que la Clase A obtenga los datos de la Clase B después de una serie de cálculos y procesamiento, y las dos clases no pueden simplemente referirse a los datos de la Clase A. Podemos considerar las devoluciones de llamada.
Los pasos son los siguientes:
Los pasos mencionados anteriormente son un poco abstractos. Veamos un ejemplo a continuación, uno es cliente y el otro es servidor. El cliente solicita los datos que requieren mucho tiempo del servidor.
Cliente de clase pública {servidor de servidor público; solicitud de cadena pública; // Enlace del servidor y obtenga la referencia del servidor. Public Client Connect (servidor de servidor) {this.server = servidor; devolver esto; } // Cliente, Establecer Solicitud pública Cliente SetRequest (solicitud de cadena) {this.Request = request; devolver esto; } // Envíe a la misma manera el método de solicitud, expresión de LamDBA. public void enqueue (servidor.Callback Callback) {new Thread (()-> Server.SetCallback (solicitud, devolución de llamada)). Start (); }} Public Class Server {public String Response = "Este es un HTML"; // Registre el método de la interfaz de devolución de llamada y pase los datos a la interfaz de devolución de llamada a través de los parámetros public void setCallback (solicitud de cadena, devolución de llamada) {System.out.println ("La solicitud se ha recibido y se está calculando ..."); new Thread (() -> {try {Thread.sleep (5000); callback.onResponse (request + respuesta);} capt (interruptedException e) {e.printstacktrace (); callback.onfail (e);}}). start (); } // Escribir una interfaz en la clase que posee la devolución de llamada de la interfaz pública de datos {void onResponse (respuesta de cadena); nulo Onfail (lanzable a tiros); }}A continuación, echemos un vistazo al ejemplo de prueba:
public class CallbackTest {public static void main (String [] args) {Client Client = new Client (); Client.Connect (nuevo server ()). SetRequest ("¿Qué es este archivo?"). Enqueue (nuevo server.callback () {@Override public void onResponse (String Response) {System.out.println (respuesta);} @Override public void onFail (showable showlable) {system.out.println (showleable.getMessage ();););});} }}Los resultados son los siguientes:
Se ha recibido la solicitud y se está calculando ... ¿Qué es este archivo? Este es un HTML
Lo anterior es comunicarse a través de devoluciones de llamada.
Lo anterior es todo el contenido de este artículo. Espero que el contenido de este artículo sea de ayuda para el estudio o el trabajo de todos. ¡También espero apoyar a Wulin.com más!