2010-08-03 9 views
135

Durante el Google IO más reciente, hubo una presentación sobre la implementación de aplicaciones de cliente relajantes. Desafortunadamente, fue solo una discusión de alto nivel sin un código fuente de la implementación.Cómo definir rellamadas en Android?

En este diagrama, en la ruta de retorno hay varias devoluciones de llamada diferentes a otros métodos.

google io presentation slide

¿Cómo se declaran lo que estos métodos son?

Entiendo la idea de una devolución de llamada: un fragmento de código que se invoca después de que se ha producido un determinado evento, pero no sé cómo implementarlo. La única forma en que he implementado devoluciones de llamada hasta ahora ha sido la anulación de varios métodos (en el resultado de la actividad, por ejemplo).

Siento que tengo una comprensión básica del patrón de diseño, pero sigo tropezando con la forma de manejar la ruta de retorno.

+3

Exactamente lo que necesita . Estaba buscando lo mismo y encontré esto: http://www.javaworld.com/javaworld/javatips/jw-javatip10.html – Sid

Respuesta

200

En muchos casos, tiene una interfaz y transmite un objeto que la implementa. Los cuadros de diálogo, por ejemplo, tienen OnClickListener.

Así como un ejemplo al azar:

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

probable que metí la pata de la sintaxis en la opción 2. Es temprano.

+4

Un buen ejemplo para entender esta técnica es cómo un fragmento debería comunicarse con otro fragmento a través de su actividad compartida: http://developer.android.com/guide/components/fragments.html#CommunicatingWithActivity – Jordy

+0

Intento "implementar" la interfaz de MyCallback en una nueva actividad que no es exitosa y el sistema requiere que edite el ruta de origen en él. Entonces, ¿cómo podría llevar a cabo "callBack" de una actividad anterior a una nueva actividad? –

+1

Dice que la variable de devolución de llamada en la clase worker es nula para mí – iYonatan

35

No es necesario definir una nueva interfaz cuando puede utilizar una existente: android.os.Handler.Callback. Pase un objeto de tipo Retrollamada e invoque el callback handleMessage(Message msg).

47

Cuando algo sucede en mi opinión me disparar un evento que mi actividad está escuchando:

// DECLARADO EN (CUSTOM) VER

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

// declarados en ACTIVIDAD

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

Si quiere saber más acerca de la comunicación (devoluciones de llamadas) betwe fragmentos en See aquí: http://developer.android.com/guide/components/fragments.html#CommunicatingWithActivity

+1

Ese tutorial de #CommunicatingWithActivity fue increíble. Finalmente entendí cómo usar devoluciones de llamada después de varios ensayos. –

+0

Gran respuesta. ¡Gracias! – iYonatan

+0

Simple y fácil de entender. ¡Gracias! –

19

para aclarar un poco en la respuesta de dragón (ya que me tomó un tiempo para averiguar qué hacer con Handler.Callback):

Handler se puede utilizar para ejecutar las devoluciones de llamada en el actual o otro hilo, pasándolo Message s. el Message contiene datos que se utilizarán a partir de la devolución de llamada. Se puede pasar un Handler.Callback al constructor de Handler para evitar extender Handler directamente. por lo tanto, a ejecutar algún código a través de devolución de llamada desde el subproceso actual:

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: acabo de dar cuenta que hay una mejor manera de obtener el mismo resultado (menos el control de exactamente cuándo ejecutar la devolución de llamada):

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

¿Tu publicación Runnable está dentro del método handleMessage? –

+0

+1 a la mejor respuesta. Me gusta más la versión 'Callback' porque es posible que no necesariamente tenga acceso a los datos que necesita' Runnable.run() 'en el momento en que lo construye – Kirby

+0

Nota:" Mientras que el constructor de Message es público, la mejor manera de obtener uno de estos es llamar a Message.obtain() o uno de los métodos Handler.obtainMessage(), que los extraerá de un grupo de objetos reciclados. " - [desde aquí] (https://developer.android.com/reference/android/os/Message.html) – jk7

16

Ejemplo para implementar el método de devolución de llamada utilizando la interfaz.

Defina la interfaz, NewInterface.java.

paquete javaapplication1;

public interface NewInterface { 
    void callback(); 
} 

Crear una nueva clase, NewClass.java. Llamará al método de devolución de llamada en la clase principal.

package javaapplication1; 

public class NewClass { 

    private NewInterface mainClass; 

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

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

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

La clase principal, JavaApplication1.java, puedan aplicar la NewInterface interfaz -() método de devolución de llamada. Creará y llamará al objeto NewClass. Luego, el objeto NewClass volverá a llamar su método de devolución de llamada().

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

hasta ahora estábamos usando las interfaces para la devolución de llamada pero ahora Square ha desarrollado una lib como event-bus Otto. Es realmente más rápido y útil. –

10

También puede usar LocalBroadcast para este fin. Aquí está una quide rápida

Crear un receptor de radiodifusión:

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 
    } 

Así es como se puede desencadenarla

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

receptor anular el registro en onPause:

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