2009-05-28 6 views
6

Estoy utilizando una biblioteca de terceros para conectarme a un servidor a través del protocolo asíncrono y obtener respuesta. Por ejemplo método para obtener ID de usuario por nombre de usuario se parece a esto:Necesito ayuda con devoluciones de llamada y clases anónimas en Java

public int getUserid(String username) { 
     int userid = 0; 

    connection.call("getUserid", new Responder() { 
     public void onResult(final int result) { 
      System.out.println("userid: " + result); 
      //how to assign received value to userid and return it? 
     } 
    }, username); 

    //wait for response 
    while (userid == 0) { 
      try{ 
       Thread.sleep(100); 
      } catch (Exception e) {} 
     } 


     return userid; 
} 

El problema es que no puede asignar regresado "número" de respuesta del servidor a "identificador de usuario" variable a partir del método (con el fin de devolverlo después) . ¿Cómo resolver esto? Probablemente pueda asignarlo a alguna variable de clase en lugar de variable de método, pero quiero mantenerlo dentro del alcance del método para no tener que lidiar con problemas de concurrencia.

Gracias.

Respuesta

2

Si entiendo su pregunta correctamente, se pregunta cómo puede escribir una variable desde dentro de una clase anónima.

Las clases anónimas solo pueden acceder a las variables finales y no pueden "escribirlas" directamente.

Una solución directa que es "suficientemente buena" es crear una especie de clase ValueBox con un solo campo de valor y un getter y setter. Luego puede crear una nueva instancia en la función como una variable final y hacer que su clase anónima acceda a ella. La clase anónima usará su getter y setter para escribir/leer.

El hecho de que la variable sea definitiva solo significa que no puede apuntar la referencia a ningún otro lado, pero aún puede cambiar el contenido del objeto referido desde cualquiera de las funciones.

El problema más grande que tendrá es esperar hasta que se haya llamado a la devolución de llamada. Este tipo de espera podría ser suficiente, pero es posible que desee considerar los tiempos de espera, los hilos, etc., dependiendo de lo que intente lograr.

Además, todo esto supone que nunca va a llamar esto dos veces en la conexión. De lo contrario, debe proporcionarnos más información sobre su modelo de sincronización.

He aquí algunos ejemplos de código:

public int getUserid(String username) { 
     final ValueBox<Integer> userid = new ValueBox<Integer>(); 

     connection.call("getUserid", new Responder() { 
       public void onResult(final int result) { 
         System.out.println("userid: " + result); 
         userId.setValue(result); 
         //how to assign received value to userid and return it? 
       } 
     }, username); 

     //wait for response 
     while (userid.isEmpty()) { 
       try{ 
         Thread.sleep(100); 
       } catch (Exception e) {} 
     } 

     return userid.getValue(); 
} 
+0

Gracias. Sin embargo, debe llamarse más de una vez ... ¿Qué modelo de sincronización quiere decir leer/escribir desde este objeto ValueBox? Va a ser bastante complicado ... – serg

+0

El problema es que podría tener varias llamadas a getUserId antes de procesar el userId (por ejemplo, imagine que tuvo 5 llamadas en los primeros 100ms). Entonces correría el riesgo de sobrescribir las cosas, etc. ¿Qué quiere hacer en esas situaciones? – Uri

+0

Probablemente no procese más solicitudes hasta que se complete la actual. – serg

0

El cambio más sencillo es usar algo como java.util.concurrent.SynchronousQueue. Pero posiblemente quiera proporcionar una interfaz impulsada por eventos usted mismo.

Cuestiones relacionadas