Android'de Geri Çağrılar Nasıl Tanımlanır?


152

En son Google ES'de, dinlendirici istemci uygulamalarının uygulanması hakkında bir sunum yapıldı. Ne yazık ki, uygulamanın kaynak kodu bulunmayan yalnızca üst düzey bir tartışma idi.

Bu diyagramda, dönüş yolunda diğer yöntemlere yönelik çeşitli farklı geri çağrılar vardır.

google io sunum slaydı

Bu yöntemlerin ne olduğunu nasıl bildirebilirim?

Geri arama fikrini anlıyorum - belirli bir olay gerçekleştikten sonra çağrılan bir kod parçası, ancak nasıl uygulanacağını bilmiyorum. Şimdiye kadar geri çağrıları uyguladığım tek yol çeşitli yöntemleri geçersiz kılıyor (örneğin onActivityResult).

Tasarım deseni hakkında temel bir anlayışa sahip olduğumu hissediyorum, ancak geri dönüş yolunu nasıl ele alacağımı düşünmeye devam ediyorum.


3
Tam olarak neye ihtiyacınız var. Ben de aynı şeyi arıyordum ve bununla
Sid

Yanıtlar:


218

Çoğu durumda, bir arabiriminiz vardır ve onu uygulayan bir nesneyi iletirsiniz. Örneğin iletişim kutularında OnClickListener bulunur.

Rastgele bir örnek olarak:

// 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
   }
};

Muhtemelen 2. seçenekteki sözdizimini berbat ettim. Erken.


5
Bu tekniğe hakim olmak için iyi bir örnek, bir parçanın paylaşılan bir parçayla başka bir parçayla nasıl iletişim kurması gerektiğidir Etkinlik: developer.android.com/guide/components/…
Jordy

Başarılı olmayan yeni bir etkinlikte MyCallback arabirimini "uygulamaya" çalışıyorum ve sistem, kaynak yolunu düzenlememi gerektiriyor. Peki eski bir aktiviteden yeni bir aktiviteye nasıl "geri arama" yapabilirim?
Antoine Murion

3
İşçi sınıfındaki geri çağırma değişkeninin benim için boş olduğunu söylüyor
iYonatan

Birisi kotlin eşdeğerini verebilir mi?
Tooniis

52

Benim görüşüme göre bir şey olduğunda, faaliyetimin dinlediği bir olayı tetiklerim:

// (ÖZEL) GÖRÜNÜMDE BEYAN

    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;
    }

// FAALİYETTE BEYAN

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

Parçalar arasındaki iletişim (geri aramalar) hakkında daha fazla bilgi edinmek için buraya bakın: http://developer.android.com/guide/components/fragments.html#CommunicatingWithActivity


1
#CommunicatingWithActivity öğreticisi harikaydı. Son olarak, birkaç denemeden sonra geri aramaların nasıl kullanılacağı anlaşıldı.
Moises Jimenez

Mükemmel cevap. Teşekkürler!
iYonatan

Basit ve kolay anlaşılır. Teşekkürler!
Glenn J.Schworak

38

Varolan bir birini kullanabilirsiniz zaman gerek yok yeni bir arayüz tanımlamak için: android.os.Handler.Callback. Geri Arama türünde bir nesneyi iletin ve geri çağrıları çağırın handleMessage(Message msg).


Ama nasıl yapmalı?
majurageerthan

26

Arayüzü kullanarak geri arama yöntemini uygulama örneği.

NewInterface.java arayüzünü tanımlayın .

paket javaapplication1;

public interface NewInterface {
    void callback();
}

Yeni bir sınıf oluşturun, NewClass.java . Ana sınıfta geri arama yöntemini çağıracaktır.

package javaapplication1;

public class NewClass {

    private NewInterface mainClass;

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

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

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

Ana sınıf JavaApplication1.java, arabirimi NewInterface - callback () yöntemini uygulamak için. NewClass nesnesini oluşturur ve çağırır. Ardından, NewClass nesnesi bunun geri çağırma () yöntemini geri çağırır.

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
Şimdiye kadar ara yüzleri geri arama için kullanıyorduk, ancak şimdi kare olay otobüsü Otto olarak bir lib geliştirdi.
Amol Patil

20

ejderhanın cevabında biraz açıklığa kavuşmak için (ne yapacağımı anlamam biraz zaman aldığından Handler.Callback):

Handlergeçerli veya başka bir iş parçacığında geri çağrıları iletmek için kullanılabilir Message. MessageVeri geri arama kullanılacak olan tutar. Bir Handler.Callbackyapıcısına geçirilebilir Handler, doğrudan Handler uzanan önlemek için. böylece, geçerli iş parçacığından geri arama yoluyla bazı kodları yürütmek için:

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);

EDIT: aynı sonucu elde etmek için daha iyi bir yol olduğunu fark ettim (eksi tam olarak ne zaman geri arama yapmak için kontrol):

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

1
Runnable postanız handleMessage yönteminin içinde mi?
IgorGanapolsky

En iyi yanıt için +1. Gibi Callbackdaha iyi sürümü mutlaka ihtiyaç duyduğu verilere erişimi olmayabilir çünkü Runnable.run()bunu inşa o zaman
Kirby

Not: "İleti kurucusu herkese açık olsa da, bunlardan birini almanın en iyi yolu Message.obtain () veya onları geri dönüştürülmüş nesneler havuzundan çekecek Handler.obtainMessage () yöntemlerinden birini çağırmaktır." - buradan
jk7

10

LocalBroadcastBu amaçla da kullanabilirsiniz . İşte hızlı bir quide

Yayın alıcısı oluşturma:

   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
    }

Bu şekilde tetikleyebilirsiniz

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

onPause'ta alıcıyı kaydet

protected void onPause() {
  super.onPause();
  LocalBroadcastManager.getInstance(this).unregisterReceiver(mMessageReceiver);
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.