안드로이드에서 콜백을 정의하는 방법?


152

가장 최근의 Google IO 동안 편안한 클라이언트 응용 프로그램 구현에 대한 프레젠테이션이있었습니다. 불행히도, 구현의 소스 코드가없는 높은 수준의 토론이었습니다.

이 다이어그램에서 리턴 경로에는 다른 메소드에 대한 다양한 콜백이 있습니다.

Google iOS 프레젠테이션 슬라이드

이 방법들이 무엇인지 어떻게 선언합니까?

콜백이라는 아이디어를 이해합니다. 특정 이벤트가 발생한 후 호출되는 코드이지만 구현 방법을 모르겠습니다. 지금까지 콜백을 구현 한 유일한 방법은 다양한 메소드 (예 : onActivityResult)를 재정의했습니다.

디자인 패턴에 대한 기본 지식이 있다고 생각하지만 리턴 경로를 처리하는 방법에 대해 계속해서 넘어갑니다.


3
정확히 필요한 것. 나는 같은 것을 찾고 있었고 이것을 가로 질러왔다 : javaworld.com/javaworld/javatips/jw-javatip10.html
Sid

답변:


218

대부분의 경우 인터페이스가 있으며이를 구현하는 객체를 전달합니다. 예를 들어 대화 상자에는 OnClickListener가 있습니다.

임의의 예와 마찬가지로 :

// The callback interface
interface MyCallback {
    void callbackCall();
}

// The class that takes the callback
class Worker {
   MyCallback callback;

   void onEvent() {
      callback.callbackCall();
   }
}

// Option 1:

class Callback implements MyCallback {
   void callbackCall() {
      // callback code goes here
   }
}

worker.callback = new Callback();

// Option 2:

worker.callback = new MyCallback() {

   void callbackCall() {
      // callback code goes here
   }
};

아마도 옵션 2의 구문을 엉망으로 만들었습니다.


5
이 기법을 익히는 좋은 예는 프래그먼트가 공유 된 액티비티를 통해 프래그먼트가 다른 프래그먼트와 통신하는 방법입니다. developer.android.com/guide/components/…
Jordy

성공하지 못한 새 활동에서 MyCallback 인터페이스를 "구현"하려고 시도하고 시스템에서 소스 경로를 편집해야합니다. 그렇다면 기존 활동에서 새로운 활동으로 "콜백"을 어떻게 수행 할 수 있습니까?
Antoine Murion

3
그것은 노동자 클래스의 콜백 변수가 나를 위해 null이라고 말합니다
iYonatan

누군가 kotlin에게 동등한 것을 줄 수 있습니까?
Tooniis

52

내 견해에서 무언가가 발생하면 내 활동이 듣고있는 이벤트를 시작합니다.

// (사용자 정의)보기에서 선언

    private OnScoreSavedListener onScoreSavedListener;
    public interface OnScoreSavedListener {
        public void onScoreSaved();
    }
    // ALLOWS YOU TO SET LISTENER && INVOKE THE OVERIDING METHOD 
    // FROM WITHIN ACTIVITY
    public void setOnScoreSavedListener(OnScoreSavedListener listener) {
        onScoreSavedListener = listener;
    }

// 활동 선언

    MyCustomView slider = (MyCustomView) view.findViewById(R.id.slider)
    slider.setOnScoreSavedListener(new OnScoreSavedListener() {
        @Override
        public void onScoreSaved() {
            Log.v("","EVENT FIRED");
        }
    });

조각 간의 통신 (콜백)에 대한 자세한 내용은 다음을 참조하십시오. http://developer.android.com/guide/components/fragments.html#CommunicatingWithActivity


1
#CommunicatingWithActivity 튜토리얼은 대단했습니다. 마지막으로 몇 번의 시험 후 콜백 사용 방법을 이해했습니다.
Moises Jimenez

좋은 대답입니다. 감사!
iYonatan

간단하고 이해하기 쉽습니다. 감사!
Glenn J. Schworak

38

기존 인터페이스를 사용할 수있을 때 새 인터페이스를 정의 할 필요가 없습니다 android.os.Handler.Callback. 콜백 유형의 객체를 전달하고 콜백을 호출 handleMessage(Message msg)합니다.


그러나 어떻게해야합니까?
majurageer2

26

인터페이스를 사용하여 콜백 메소드를 구현하는 예제입니다.

NewInterface.java 인터페이스를 정의하십시오 .

패키지 javaapplication1;

public interface NewInterface {
    void callback();
}

새 클래스 NewClass.java를 작성하십시오 . 메인 클래스에서 콜백 메소드를 호출합니다.

package javaapplication1;

public class NewClass {

    private NewInterface mainClass;

    public NewClass(NewInterface mClass){
        mainClass = mClass;
    }

    public void calledFromMain(){
        //Do somthing...

        //call back main
        mainClass.callback();
    }
}

인터페이스 NewInterface-callback () 메소드를 구현하기위한 기본 클래스 인 JavaApplication1.java NewClass 객체를 생성하고 호출합니다. 그런 다음 NewClass 객체는 callback () 메서드를 차례로 콜백합니다.

package javaapplication1;
public class JavaApplication1 implements NewInterface{

    NewClass newClass;

    public static void main(String[] args) {

        System.out.println("test...");

        JavaApplication1 myApplication = new JavaApplication1();
        myApplication.doSomething();

    }

    private void doSomething(){
        newClass = new NewClass(this);
        newClass.calledFromMain();
    }

    @Override
    public void callback() {
        System.out.println("callback");
    }

}

1
지금까지 우리는 콜백에 인터페이스를 사용하고 있었지만 이제 square은 lib를 event-bus Otto로 개발했습니다. 정말 빠르고 유용합니다.
Amol Patil

20

용의 대답을 조금 명확히하기 위해 (어떻게 해야할지 알아내는 데 시간이 걸리기 때문에 Handler.Callback) :

Handler콜백을 전달하여 현재 또는 다른 스레드에서 콜백을 실행하는 데 사용할 수 있습니다 Message. 는 Message데이터 콜백에서 사용될 보유하고있다. Handler.Callback생성자로 전달 될 수있는 Handler직접 처리기 연장되는 것을 피하기 위해. 따라서 현재 스레드에서 콜백을 통해 일부 코드를 실행하려면 다음을 수행하십시오.

Message message = new Message();
<set data to be passed to callback - eg message.obj, message.arg1 etc - here>

Callback callback = new Callback() {
    public boolean handleMessage(Message msg) {
        <code to be executed during callback>
    }
};

Handler handler = new Handler(callback);
handler.sendMessage(message);

편집 : 방금 동일한 결과를 얻는 더 좋은 방법이 있다는 것을 깨달았습니다 (콜백을 정확히 언제 실행할지 제어).

post(new Runnable() {
    @Override
    public void run() {
        <code to be executed during callback>
    }
});

1
Runnable 게시물이 handleMessage 메소드 안에 있습니까?
IgorGanapolsky

최상의 답변을 얻으려면 +1하십시오. 등 내가 Callback더 나은 버전이 반드시 필요로하는 데이터에 대한 액세스 권한이 없을 수 있기 때문에 Runnable.run()당신이 그것을 구성하는 시간을
커비

참고 : "Message의 생성자가 공개적이지만이 중 하나를 얻는 가장 좋은 방법은 Message.obtain () 또는 Handler.obtainMessage () 메서드 중 하나를 호출하여 재활용 된 개체 풀에서 가져 오는 것입니다." - 여기에서
jk7

10

LocalBroadcast이 목적으로 도 사용할 수 있습니다 . 여기 빠른 퀘스트가 있습니다

방송 수신기를 만듭니다.

   LocalBroadcastManager.getInstance(this).registerReceiver(
            mMessageReceiver, new IntentFilter("speedExceeded"));

private BroadcastReceiver mMessageReceiver = new BroadcastReceiver() {
    @Override
    public void onReceive(Context context, Intent intent) {
        String action = intent.getAction();
        Double currentSpeed = intent.getDoubleExtra("currentSpeed", 20);
        Double currentLatitude = intent.getDoubleExtra("latitude", 0);
        Double currentLongitude = intent.getDoubleExtra("longitude", 0);
        //  ... react to local broadcast message
    }

이것이 당신이 그것을 트리거 할 수있는 방법입니다

Intent intent = new Intent("speedExceeded");
intent.putExtra("currentSpeed", currentSpeed);
intent.putExtra("latitude", latitude);
intent.putExtra("longitude", longitude);
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);

onPause에서 수신자 등록 취소 :

protected void onPause() {
  super.onPause();
  LocalBroadcastManager.getInstance(this).unregisterReceiver(mMessageReceiver);
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.