Os retornos de chamada são definidos na Wikipedia como:
Na programação de computadores, uma função de retorno de chamada refere -se a uma referência a uma determinada peça do código executável que é passado para outro código através dos parâmetros de função.
O objetivo é permitir que o código subjacente ligue para as sub -rotinas definidas no nível superior.
Por exemplo, pode ser mais claro: tomando o uso de retrofit para solicitações de rede no Android como exemplo, este é um exemplo de retornos de chamada assíncronos.
Depois de iniciar uma solicitação de rede, o aplicativo pode continuar outras coisas. O resultado da solicitação de rede é geralmente obtido através dos dois métodos de resposta e falha. Dê uma olhada no código na parte relevante:
Call.enQueue (novo retorno de chamada <SistoryBean> () {@Override public void onResponse (ligue para <SistryBean> Chamada, resposta <SistoryBean> Response) {HistoryBean Hb = Response.body (); if (hb == null) Return; showText.append (hb.error () + ""); hb.getResults ()) {showtext.append (rb.gettitle () + "/n");Ignore os genéricos no retorno de chamada acima. De acordo com a definição na Wikipedia, todo o código em uma classe interna anônima pode ser considerada uma referência a um determinado código executável que é passado para outros códigos . Os dois métodos OnResponse e OnFailure são métodos de retorno de chamada. O código subjacente é a peça de solicitação de rede inalterada que foi gravada e a sub -rotina definida pelo nível superior é o retorno de chamada. Como a implementação específica é entregue ao usuário, ela tem alta flexibilidade. O exposto acima está relacionado através do método ENQUEUE (retorno de chamada).
Etapas do método de retorno de chamada
O retorno de chamada mencionado acima é um conceito muito comum. Se você o colocar na redação do programa, pode dizer:
Na classe A, um método C na classe B é chamado e, em seguida, na classe B, o método d na classe A é chamado no contrário. D é o método de retorno de chamada. A classe B é o código subjacente e a classe A é o código de alto nível.
Assim, através da explicação acima, podemos inferir algo. Para representar a universalidade do método D, usamos o formulário de interface para fazer o método D chamado de método de interface. Se a classe B quiser chamar o método D na classe A, a classe A deverá implementar essa interface. Dessa forma, dependendo da implementação, haverá polimorfismo, tornando o método flexível.
Se a Classe A quiser chamar um método C na classe B, a classe A deve conter uma referência a B, caso contrário, ele não será chamado. Esta etapa é chamada de interface de retorno de chamada de registro. Portanto, como implementar o método de chamada reversa D na classe A na classe B, diretamente através do método acima C. Método C na classe B aceita um parâmetro de tipo de interface. Em seguida, somente no método C, você precisa usar os parâmetros desse tipo de interface para chamar o método D na classe B, que por sua vez chama o método d na classe A. Esta etapa é chamada chamando a interface de retorno de chamada.
Isso também implementa que, no método C da Classe B, o método D na classe A precisa ser chamado no verso, que é o retorno de chamada. A chamadas B para sintonizar diretamente, que pode ser considerado como usando a API subjacente para o código de alto nível. Costumamos escrever programas como este. B liga para ligar de volta, e a API subjacente requer código de alto nível para executar.
Por fim, vamos resumir as etapas do método de retorno de chamada:
Exemplo de retorno de chamada
Vamos pegar um filho jogando e esperando sua mãe preparar a refeição e notificar seu filho para comer como exemplo, e siga as etapas acima para escrever um retorno de chamada;
No exemplo acima, é óbvio que o filho deve implementar a interface de retorno de chamada e a mãe deve chamar a interface de retorno de chamada. Então, definimos primeiro uma interface de retorno de chamada e depois deixamos nosso filho implementar essa interface de retorno de chamada.
O código é o seguinte:
interface pública Retorno de chamada {void eat ();} Public Class Son implementa o retorno de chamada {mamãe particular; // Classe A detém uma referência à classe B public void setMom (mãe mãe) {this.mom = mom; } @Override public void Eat () {System.out.println ("Estou aqui para fazer uma refeição"); } public void AskMom () {// chamando um método com parâmetros de interface através de uma referência à classe B. System.out.println ("A refeição foi cozida?"); System.out.println ("Não terminou, estou jogando o jogo"); novo thread (() -> mom.docook (SON.Este)). Start (); System.out.println ("Jogando o jogo ..."); }}Então também precisamos definir a classe de uma mãe, que contém um documento de método com parâmetros de interface
public class Mom {// Ligue para o método de retorno de chamada usando parâmetros de interface em um método que contém parâmetros de interface public void docook (retorno de chamada) {new Thread (new runnable () {@Override public void run () {Try {System.out.println ("Cooking ..."); E.PrintStackTrace (); }}Passamos uma aula de teste:
classe pública teste {public static void main (string [] args) {mãe mamãe = new Mom (); Filho filho = novo filho (); filho.setMom (mãe); SON.ASKMOM (); }}Este exemplo é um exemplo típico de retorno de chamada. A classe Son implementa o método de retorno de chamada da interface. Ele chama Docook na classe MOM através do método AskMom para registrar a interface de retorno de chamada, o que equivale a chamar o Código C da Classe B na classe A. Docook na classe Mom chama a classe Eat in the Son para informar os resultados na classe SON.
Dessa forma, implementamos um retorno de chamada simples e definido.
Exploração adicional de exemplos de retorno de chamada
Vamos olhar principalmente para o código da classe Son:
Public Class Son implementa o retorno de chamada {mãe pública mãe; filho público (mãe mãe) {this.mom = mãe; } public void AskMom () {System.out.println ("A refeição foi cozida?"); System.out.println ("Eu não fiz bem, joguei o jogo"); novo thread (() -> mom.docook (SON.Este)). Start (); System.out.println ("Estou jogando o jogo ..."); } @Override public void Eat () {System.out.println ("Ok, estou aqui para fazer uma refeição"); }}Nesta classe, além de produzir algumas declarações, as partes realmente úteis são mom.docook (filho.Este) e reescrever o método Eat. Portanto, podemos abreviar esse retorno de chamada através da forma de classe interna anônima. O código é o seguinte:
classe pública CallbackTest {public static void main (string [] args) {mãe mamãe = new Mom (); novo thread (() -> mom.docook (() -> system.out.println ("Eu tive uma refeição ..."))). start (); }}Cancele a classe SON e implemente diretamente o método Eat através da classe interna anônima no método principal. De fato, as classes internas anônimas são a personificação dos retornos de chamada.
Retornos de chamada assíncronos e retornos de chamada síncronos
Retorno de chamada: um método C de chamadas na classe B e depois chama o método d na classe A através dos objetos da classe A no método C.
Vamos falar sobre assíncrona e sincronização, vamos falar primeiro sobre o conceito de sincronização.
síncrono
A sincronização significa que, ao chamar um método, se a chamada de método anterior não for executada, uma nova chamada de método não poderá ser feita. Em outras palavras, as coisas devem ser feitas uma a uma, e você só pode fazer o próximo após o outro.
assíncrono
A assíncrona é relativa à sincronização, você não precisa esperar até que a chamada de método anterior seja concluída antes de ligar para um novo método. Portanto, em chamadas de método assíncrono, é necessário um método para notificar o usuário do resultado da chamada do método.
Implementar métodos assíncronos
A maneira mais comum de implementar assíncrona em Java é deixar o método que você deseja executar assíncrona em um novo thread.
Descobrimos que um método é necessário em uma chamada de método assíncrono para notificar o resultado da chamada do usuário. Com base no exposto, descobriremos que o método de retorno de chamada é adequado para fazer isso e notificar o usuário do resultado da chamada através do método de retorno de chamada.
O retorno de chamada assíncrono é feito em um novo tópico quando um método de chamadas C de B.
O exemplo acima da mãe notificando seu filho para o jantar é um exemplo de um retorno de chamada assíncrono. Em um novo tópico, o método Docook é chamado e o valor de retorno é finalmente aceito através do EAT. Obviamente, depois de usar a otimização do LAMDBA, a essência é a mesma.
Retorno de chamada síncrona significa que A Chamadas B Método C não em um novo thread. Ao executar esse método C, não podemos fazer nada e só podemos esperar que ele seja concluído.
Exemplos de retornos de chamada síncronos e retornos de chamada assíncronos
Vejamos um exemplo de retorno de chamada síncrona no Android:
Button.SetOnClickListener (new View.OnClickListener () {@Override public void OnClick (View V) {Log.i ("Button", "Clicked");}});O botão registra a função de retorno de chamada através do setOnClickListener e, como escrito acima, passa a referência da interface na forma de uma classe interna anônima. Como o botão chama setOnClickListener sem criar um novo thread, este é um retorno de chamada síncrono.
Retorno de chamada assíncrona é o exemplo de que falamos no início:
Call.enQueue (novo retorno de chamada <SistoryBean> () {@Override public void onResponse (ligue para <SistryBean> Chamada, resposta <SistoryBean> Response) {HistoryBean Hb = Response.body (); if (hb == null) Return; showText.append (hb.error () + ""); hb.getResults ()) {showtext.append (rb.gettitle () + "/n");Esse método de enquadrão é um método assíncrono para solicitar dados de rede remota. Quando é implementado internamente, é executado através de um novo thread.
Através desses dois exemplos, podemos ver que o uso de retornos de chamada síncronos e retornos de chamada assíncronos é realmente projetado de acordo com diferentes necessidades. Não se pode dizer que um substitui o outro. Por exemplo, no evento de clique em botão acima, se for um retorno de chamada assíncrono, o efeito de clique não aparecerá imediatamente depois que o usuário clica no botão e o usuário não executará outras operações, ele parecerá estranho. Retornos de chamada assíncronos para solicitações de rede, como o recurso solicitado pode não existir, a conexão de rede é instável e outros motivos, o usuário não é claro sobre a execução do método, para que eles usem retornos de chamada assíncronos, iniciem o método chamada e faça outras coisas e, em seguida, aguardam a notificação de retorno de chamada.
Aplicação do método de retorno de chamada na comunicação
Os métodos de retorno de chamada mencionados acima, exceto os retornos de chamada da estrutura de solicitação de rede, todos não têm parâmetros. Vamos dar uma olhada na adição de parâmetros ao método de retorno de chamada para implementar alguns problemas de comunicação.
Se queremos que a Classe A obtenha os dados da Classe B após uma série de cálculos e processamento, e as duas classes não podem simplesmente se referir aos dados da Classe A. Podemos considerar retornos de chamada.
As etapas são as seguintes:
As etapas mencionadas acima são um pouco abstratas. Vejamos um exemplo abaixo, um é o cliente e o outro é o servidor. O cliente solicita os dados demorados do servidor.
public class Client {public Server Server; solicitação pública de string; // Link Server e obtenha a referência do servidor. public Client Connect (Server Server) {this.server = server; devolver isso; } // cliente, defina solicitação public client setRequest (solicitação de string) {this.request = request; devolver isso; } // Envie de maneira bem o método de solicitação, expressão lamdba. public void enqueue (server.callback de retorno) {new thread (()-> server.setCallback (solicitação, retorno de chamada)). start (); }} public class Server {public String Response = "Este é um html"; // Registre o método da interface de retorno de chamada e passa os dados para a interface de retorno de chamada através dos parâmetros public void setCallback (solicitação de string, retorno de chamada) {System.out.println ("A solicitação foi recebida e está sendo calculada ..."); novo thread (() -> {tente {thread.sleep (5000); retorno de chamada.onResponse (request + resposta);} catch (interruptedException e) {e.printStacktrace (); retorno de chamada.onfail (e);}}). start (); } // Escreva uma interface na classe que possui o retorno de chamada da interface pública de dados {void onResponse (resposta da string); vazio onfail (jogável lançável); }}Em seguida, vamos dar uma olhada no exemplo de teste:
classe pública CallbackTest {public static void main (string [] args) {client client = new client (); client.Connect (new Server ()). SetRequest ("O que é esse arquivo?"). ENQUEUE (new Server.Callback () {@Override public void onResponse (String Response) {System.out.Println (resposta);} @Override public void OnFail (Throwable) {System.out.out.Int.Int); }}Os resultados são os seguintes:
A solicitação foi recebida e está sendo calculada ... O que é esse arquivo? Este é um html
O exposto acima é se comunicar através de retornos de chamada.
O exposto acima é todo o conteúdo deste artigo. Espero que o conteúdo deste artigo seja de ajuda para estudar ou trabalhar de todos. Eu também espero apoiar mais wulin.com!