2010-08-03 14 views
135

Durante il più recente Google IO, è stata presentata una presentazione sull'implementazione di applicazioni client restful. Sfortunatamente, era solo una discussione di alto livello senza codice sorgente dell'implementazione.Come definire le callback in Android?

In questo diagramma, sul percorso di ritorno sono disponibili diverse richiamate per altri metodi.

google io presentation slide

Come dichiaro ciò che questi metodi sono?

Ho compreso l'idea di un callback, un pezzo di codice che viene chiamato dopo un determinato evento, ma non so come implementarlo. L'unico modo in cui ho implementato le richiamate finora è stato l'override di vari metodi (ad esempio, adActivityResult).

Mi sento come se avessi una comprensione di base del modello di progettazione, ma continuo a essere inciampato su come gestire il percorso di ritorno.

+3

esattamente ciò che serve . Stavo cercando la stessa cosa e mi sono imbattuto in questo: http://www.javaworld.com/javaworld/javatips/jw-javatip10.html – Sid

risposta

200

In molti casi, si dispone di un'interfaccia e si passa un oggetto che lo implementa. Le finestre di dialogo, ad esempio, hanno OnClickListener.

Proprio come un esempio a caso:

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

probabilmente ho incasinato la sintassi nell'opzione 2. E 'presto.

+4

Un buon esempio per prendere confidenza con questa tecnica è come un frammento dovrebbe comunicare con un altro frammento attraverso la sua attività condivisa: http://developer.android.com/guide/components/fragments.html#CommunicatingWithActivity – Jordy

+0

Tento di "implementare" l'interfaccia MyCallback in una nuova attività che non ha esito positivo e il sistema mi richiede di modificare il percorso sorgente su di esso. Quindi, come potrei eseguire "callBack" da una vecchia attività a una nuova attività? –

+1

Dice che la variabile di callback nella classe worker è nulla per me – iYonatan

35

Non è necessario definire una nuova interfaccia quando è possibile utilizzare uno esistente: android.os.Handler.Callback. Passa un oggetto di tipo Callback e invoca il callback handleMessage(Message msg).

47

Quando succede qualcosa a mio avviso ho sparare un evento che la mia attività è in ascolto per:

// DICHIARATO IN (CUSTOM) VISTA

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

// dichiarati nel ATTIVITA

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

Se si desidera saperne di più sulla comunicazione (callback) tra frammenti en vedere qui: http://developer.android.com/guide/components/fragments.html#CommunicatingWithActivity

+1

Quel tutorial #CommunicatingWithActivity è stato fantastico. Finalmente ho capito come usare i callback dopo diverse prove. –

+0

Ottima risposta. Grazie! – iYonatan

+0

Semplice e facile da capire. Grazie! –

19

per chiarire un po 'la risposta del drago (in quanto ci ho messo un po' per capire cosa fare con Handler.Callback):

Handler può essere utilizzato per eseguire i callback nell'anno in corso o un altro thread, passandolo a Message s. il Message conserva i dati da utilizzare dalla richiamata. a Handler.Callback può essere passato al costruttore di Handler per evitare di estendere direttamente l'Handler. pertanto, di eseguire del codice tramite richiamata dal thread corrente:

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: appena realizzato c'è un modo migliore per ottenere lo stesso risultato (meno il controllo di esattamente quando eseguire il callback):

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

Il tuo post Runnable è all'interno del metodo handleMessage? –

+0

+1 per la migliore risposta. Mi piace la versione di 'Callback' meglio perché potresti non avere necessariamente accesso ai dati necessari a' Runnable.run() 'nel momento in cui la costruisci – Kirby

+0

Nota:" Mentre il costruttore di Message è pubblico, il modo migliore per ottenere uno di questi è chiamare Message.obtain() o uno dei metodi Handler.obtainMessage(), che li estrarrà da un pool di oggetti riciclati. " - [da qui] (https://developer.android.com/reference/android/os/Message.html) – jk7

16

Esempio per implementare il metodo di callback tramite l'interfaccia.

Definire l'interfaccia, NewInterface.java.

pacchetto javaapplication1;

public interface NewInterface { 
    void callback(); 
} 

Creare una nuova classe, NewClass.java. Chiamerà il metodo di callback nella classe principale.

La classe principale, JavaApplication1.java, per implementare l'interfaccia NewInterface - metodo callback(). Creerà e chiamerà oggetto NewClass. Quindi, l'oggetto NewClass chiamerà a sua volta il metodo 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"); 
    } 

} 
+0

fino ad ora stavamo usando le interfacce per il callback ma ora square ha sviluppato una lib come event bus Otto. È davvero più veloce e utile. –

10

È inoltre possibile utilizzare LocalBroadcast per questo scopo. Ecco una rapida quide

Creare un ricevitore di broadcast:

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 
    } 

Questo è come si può innescare

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

ricevitore annullare la registrazione in onPause:

protected void onPause() { 
    super.onPause(); 
    LocalBroadcastManager.getInstance(this).unregisterReceiver(mMessageReceiver); 
} 
Problemi correlati