Java 콜백 방법 상세 정보
컴퓨터 프로그램 설계에서 리셋 함수는 함수 파라미터를 통해 다른 코드로 전달되는 실행 가능한 코드의 인용을 가리킨다.
그 목적은 하부 코드가 고위층에서 정의한 하위 프로그램에 호출되는 것을 허용하는 것이다.
예를 들면 좀 더 알 수 있다. 안드로이드에서retrofit로 네트워크 요청을 하는 것을 예로 들면, 이것은 비동기적인 리셋의 한 예이다.
네트워크 요청을 시작한 후에 앱은 다른 일을 계속할 수 있습니다. 네트워크 요청의 결과는 일반적으로 onResponse와 onFailure 두 가지 방법을 통해 되돌아옵니다.관련 부분의 코드를 보십시오.
call.enqueue(new Callback<HistoryBean>() {
@Override
public void onResponse(Call<HistoryBean> call, Response<HistoryBean> response) {
HistoryBean hb = response.body();
if(hb == null) return;
showText.append(hb.isError() + "");
for(HistoryBean.ResultsBean rb : hb.getResults()){
showText.append(rb.getTitle() + "/n");
}
}
@Override
public void onFailure(Call<HistoryBean> call, Throwable t) {
}
});
위 CallBack의 범주를 무시하고 위키백과에 정의된 대로 익명 내부 클래스의 모든 코드는 함수 파라미터가 다른 코드로 전달되는 실행 가능한 코드의 인용으로 볼 수 있습니다.onResponse와 onFailure 두 가지 방법이 리셋 방법입니다.밑바닥의 코드는 이미 변하지 않는 네트워크 요청 부분을 작성했고 고위층이 정의한 하위 프로그램은 리셋이다. 구체적인 실현은 사용자에게 맡기기 때문에 높은 유연성을 갖추고 있다.위쪽은 enqueue(Callback callback)라는 방법으로 연결되어 있습니다.리셋 방법의 단계
위에서 말한 리셋은 매우 통용되는 개념으로 프로그램에 올려 쓰면 다음과 같이 말할 수 있다.
A클래스에서 B클래스의 어떤 방법인 C를 호출하고 B클래스에서 A클래스의 방법인 D를 반대로 호출하면 이 안에서 D가 리셋 방법이다.B류는 바로 밑바닥의 코드이고, A류는 고위층의 코드이다.
그래서 위의 해석을 통해 우리는 몇 가지 추측할 수 있다. D 방법의 통용성을 나타내기 위해 우리는 인터페이스의 형식으로 D 방법을 하나의 인터페이스 방법이라고 부른다. 만약에 B 클래스가 A 클래스 중의 방법 D를 호출하려면 반드시 A 클래스가 이 인터페이스를 실현해야 한다. 그러면 실현에 따라 다태성이 있어 방법이 유연성을 가지게 된다.
A클래스는 B클래스의 어떤 방법인 C를 호출하려면 반드시 A클래스에 B의 인용을 포함해야 한다. 그렇지 않으면 호출할 수 없다. 이 단계를 등록 리셋 인터페이스라고 부른다.그렇다면 어떻게 B류에서 A류의 방법 D를 거꾸로 호출할 수 있을까? 바로 위의 방법 C를 통해 B류의 방법 C는 하나의 인터페이스 유형의 매개 변수를 받아들인다. 그러면 C방법에서 이 인터페이스 유형의 매개 변수로 D방법을 호출하면 B류에서 반대로 A류의 방법 D를 호출하는 것을 호출 리셋 인터페이스라고 부른다.
이것 또한 B류의 C방법에서 A류의 D방법을 반대로 다시 호출해야 한다는 것을 실현했다. 이것이 바로 리셋이다.A 호출 B는 직조입니다. 고위층 코드는 밑바닥 API로 볼 수 있습니다. 우리는 자주 이렇게 프로그램을 씁니다.B 호출 A는 리셋이며 베이스 API는 높은 수준의 코드가 필요합니다.
마지막으로 리셋 방법의 절차를 요약합니다.
우리는 한 아들이 게임을 하고 있는데 엄마가 밥을 다 지으면 아들에게 먹으라고 통지하는 것을 예로 삼아 위의 절차에 따라 답장을 쓴다.
위의 예에서 분명히 아들이 리셋 인터페이스를 실현해야 하고 어머니는 리셋 인터페이스를 사용해야 한다.그래서 우리는 먼저 리셋 인터페이스를 정의한 다음에 아들에게 이 리셋 인터페이스를 실현하도록 한다.
코드는 다음과 같습니다.
public interface CallBack {
void eat();
}
public class Son implements CallBack{
private Mom mom;
//A B
public void setMom(Mom mom){
this.mom = mom;
}
@Override
public void eat() {
System.out.println(" ");
}
public void askMom(){
// B 。
System.out.println(" ?");
System.out.println(" , ");
new Thread(() -> mom.doCook(Son.this)).start();
System.out.println(" ......");
}
}
그리고 우리는 어머니의 클래스를 정의해야 한다. 인터페이스 파라미터를 포함하는 방법이 있다.
public class Mom {
//
public void doCook(CallBack callBack){
new Thread(new Runnable() {
@Override
public void run() {
try {
System.out.println(" ......");
Thread.sleep(5000);
callBack.eat();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
}
}
우리는 테스트 클래스를 통과했다.
public class Test {
public static void main(String[] args) {
Mom mom = new Mom();
Son son = new Son();
son.setMom(mom);
son.askMom();
}
}
이 예가 바로 전형적인 반조의 예다.Son클래스는 인터페이스의 리셋 방법을 실현했다. askMom이라는 방법을 통해 Mom클래스의 DoCook을 호출하여 리셋 인터페이스를 등록하는 것을 실현했다. 이는 A클래스에서 B클래스를 호출하는 코드 C에 해당한다.Mom 클래스의 DoCook에서 Son 클래스의 eat를 리셋하여 Son 클래스의 결과를 알려줍니다.이렇게 해서 우리는 간단하고 정의에 부합되는 리셋을 실현했다.
리셋 예의 진일보한 탐색
우리는 주로 Son 클래스의 코드를 보았다.
public class Son implements CallBack{
public Mom mom;
public Son(Mom mom){
this.mom = mom;
}
public void askMom(){
System.out.println(" ?");
System.out.println(" , ");
new Thread(() -> mom.doCook(Son.this)).start();
System.out.println(" ......");
}
@Override
public void eat() {
System.out.println(" , ");
}
}
이 종류 안에서 일부 문장을 출력하는 것 외에 진정으로 유용한 부분은mom이다.DoCook(Son.this) 및 eat 다시 쓰기 방법그래서 우리는 익명 내부류의 형식을 통해 이 회조를 간단하게 쓸 수 있다.코드는 다음과 같습니다.
public class CallBackTest {
public static void main(String[] args) {
Mom mom = new Mom();
new Thread(()-> mom.doCook(() -> System.out.println(" ......"))).start();
}
}
Son 클래스를 취소하고 주 방법에서 익명 내부 클래스를 통해 eat 방법을 직접 실현합니다.사실 익명 내부류는 리셋의 구현이다.비동기식 리셋과 동기식 리셋
리셋에서 우리가 말한 것은 바로 A가 B류의 방법 C를 호출하고 방법 C에서 A류의 대상을 통해 A류의 방법 D를 호출하는 것이다.
우리는 비동기화와 동기화를 이야기하고 있는데, 먼저 동기화의 개념을 말한다
동기화
동기화는 방법을 호출할 때 이전 방법의 호출이 완료되지 않으면 새로운 방법을 호출할 수 없다는 것을 가리킨다.즉, 일은 반드시 한 가지 한 가지 일을 해야 하고, 지난 일을 끝내야만 다음 일을 할 수 있다는 것이다.
비동기
비동기화는 동기화에 비해 이전 방법의 호출이 끝날 때까지 기다리지 않고 새로운 방법을 호출할 수 있다.따라서 비동기적인 방법 호출에서 사용자에게 방법 호출 결과를 알리는 방법이 필요하다.
비동기식 구현
자바에서 가장 자주 이루어지는 비동기 방식은 비동기적인 방법을 새로운 라인에서 실행하도록 하는 것이다.
우리는 비동기적인 방법 호출 중 사용자의 호출 결과를 통지하는 방법이 필요하다는 것을 발견할 수 있다. 위에서 말한 바와 결합하면 우리는 리셋 방법이 이 일을 하기에 적합하다는 것을 발견하고 리셋 방법을 통해 사용자가 호출한 결과를 통지할 수 있다.
그 비동기 리셋은 A가 B를 호출하는 방법이다. C는 새로운 라인에서 하는 것이다.
위의 어머니가 아들에게 밥을 먹으라고 통지한 예가 바로 비동기적인 답조의 예이다.새로운 라인에서 DoCook 방법을 호출하고 마지막으로 eat를 통해 되돌아오는 값을 받아들인다. 물론lamdba 최적화를 사용한 후의 본질은 같다.
동기화 리셋은 A가 B를 호출하는 방법입니다. C는 새로운 라인에 없습니다. 이 방법 C를 실행할 때 우리는 아무것도 할 수 없습니다. 그가 실행하기를 기다릴 수밖에 없습니다.
동기화 리셋과 비동기화 리셋의 예
Android의 동기식 리셋 예를 살펴보겠습니다.
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.i("button"," ");
}
});
button은 setOnClickListener를 통해 리셋 함수를 등록하고 위에 적힌 것과 같이 익명 내부 클래스 형식으로 인터페이스의 인용을 전송합니다.button 호출 setOnClickListener에 새 라인이 없기 때문에 동기화된 리셋입니다.비동기적인 답조는 바로 우리가 처음에 말한 그 예이다.
call.enqueue(new Callback<HistoryBean>() {
@Override
public void onResponse(Call<HistoryBean> call, Response<HistoryBean> response) {
HistoryBean hb = response.body();
if(hb == null) return;
showText.append(hb.isError() + "");
for(HistoryBean.ResultsBean rb : hb.getResults()){
showText.append(rb.getTitle() + "/n");
}
}
@Override
public void onFailure(Call<HistoryBean> call, Throwable t) {
}
});
이 enqueue 방법은 원격 네트워크 데이터를 요청하는 비동기적인 방법입니다.그 내부가 실현될 때는 새로운 라인을 통해 실행된다.이 두 가지 예를 통해 우리는 동기 리셋과 비동기 리셋의 사용이 사실은 서로 다른 수요에 따라 설계된 것을 알 수 있다.다른 것을 대체하는 것은 말할 수 없다. 예를 들어 위의 단추 클릭 사건에서 비동기적인 리셋이라면 사용자가 단추를 클릭한 후에 그 클릭 효과가 바로 나타나는 것이 아니라 사용자가 다른 조작을 하지 않으면 이상하게 느낄 것이다.한편, 네트워크 요청의 비동기적인 리셋은 요청 자원이 존재하지 않을 수 있고 네트워크 연결이 불안정하기 때문에 사용자가 방법을 잘 알지 못할 때 비동기적인 리셋을 사용하여 방법을 호출한 후에 다른 일을 하고 리셋의 통지를 기다린다.
리셋 방법의 통신에서의 응용
위에서 언급한 리셋 방법은 네트워크 요청 프레임워크의 리셋을 제외하고 그 리셋 방법은 모두 파라미터가 없다. 다음은 리셋 방법에 파라미터를 추가하여 통신 문제를 실현하는 것을 보자.
만약에 우리가 B류가 일련의 계산을 거쳐 처리된 데이터를 얻고 싶다면 두 종류는 간단하게 B류를 A류에 인용하면 데이터를 얻을 수 없다.우리는 답조를 고려할 수 있다.
단계는 다음과 같습니다.
public class Client{
public Server server;
public String request;
// Server, Server 。
public Client connect(Server server){
this.server = server;
return this;
}
//Client, request
public Client setRequest(String request){
this.request = request;
return this;
}
// ,lamdba 。
public void enqueue(Server.CallBack callBack){
new Thread(()->server.setCallBack(request,callBack)).start();
}
}
public class Server {
public String response = " html";
// ,
public void setCallBack(String request,CallBack callBack){
System.out.println(" request, ......");
new Thread(() -> {
try {
Thread.sleep(5000);
callBack.onResponse(request + response);
} catch (InterruptedException e) {
e.printStackTrace();
callBack.onFail(e);
}
}).start();
}
//
public interface CallBack{
void onResponse(String response);
void onFail(Throwable throwable);
}
}
다음은 테스트의 예를 살펴보겠습니다.
public class CallBackTest {
public static void main(String[] args) {
Client client = new Client();
client.connect(new Server()).setRequest(" ?").enqueue(new Server.CallBack() {
@Override
public void onResponse(String response) {
System.out.println(response);
}
@Override
public void onFail(Throwable throwable) {
System.out.println(throwable.getMessage());
}
});
}
}
결과는 다음과 같습니다.
request, ......
? html
이상은 리셋을 통해 통신하는 것이다.이상은 본문의 전체 내용입니다. 본고의 내용이 여러분의 학습이나 업무에 일정한 도움을 줄 수 있는 동시에 저희를 많이 지지해 주시기 바랍니다!
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
JPA + QueryDSL 계층형 댓글, 대댓글 구현(2)이번엔 전편에 이어서 계층형 댓글, 대댓글을 다시 리팩토링해볼 예정이다. 이전 게시글에서는 계층형 댓글, 대댓글을 구현은 되었지만 N+1 문제가 있었다. 이번에는 그 N+1 문제를 해결해 볼 것이다. 위의 로직은 이...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.