2012-04-03 22 views
5

Actualmente estoy desarrollando la capa de presentación de una aplicación de Android.¿La solución más elegante para encadenar llamadas asíncronas en java?

la API, que estoy usando miradas algo como esto:

public interface errorInterface{ 
    public void onError(String reason); 
} 

public interface if1 extends errorInterface{ 
    public void dataReceived1(Data data); 
} 
public interface if2 extends errorInterface{ 
    public void dataReceived2(Data data); 
} 

public void fetchData1(if1 receiver) {} 
public void fetchData2(if2 receiver) {} 

Eso es; para obtener datos usted proporciona un receptor que recibirá el resultado de la operación en algún momento en el futuro.

Esto funciona muy bien cuando solo necesita llamar a un método a la vez, pero ahora he llegado al punto en que necesito llamar a más de 10 de esos métodos de una sola vez, y deben ejecutarse uno a la vez.

¿Cómo puedo resolver esto de una manera flexible y elegante?

Gracias!

Respuesta

7

Vamos a hacer seguro de entender .. usted tiene una serie de interfaces if1, if2 .. ifn y quiere que todos sean capaces de procesar los datos recibido.

En primer lugar, sería mejor si if1, if2, etc eran todos de la misma interfaz con los dos métodos básicos: public void dataReceived(Data d) y public void onError(String reason). Con eso, puede simplemente pasar un List o Collection de sus receptores a fetchData y puede iterar sobre la colección y llamar al dataReceived(d) en cada uno.

Si, por alguna razón, eso no funciona, probaría un adaptador para convencerlos en una interfaz similar para fetchData. Por ejemplo:

public interface DataReceiver extends ErrorInterface { 
    public void dataReceived(Data d); 
    //or just scrap the ErrorInterface all together and make these into 1 interface 
} 

public class AbstractIFAdapter<T extends ErrorInterface> implements DataReceiver { 
    private T target; 
    public AbstractIFAdapter(T target) { this.target = target); 
    public void onError(String reason) { target.onError(reason); } 
    protected T getTarget() { return target; } 
} 

public class IF1Adapter extends AbstractIFAdapter<IF1> { 
    public IF1Adapter(IF1 target) { super(target); } 
    public dataReceived(Data d) { getTarget().dataReceived1(d); } 
} 

public class IF2Adapter extends AbstractIFAdapter<IF2> { 
    public IF2Adapter(IF2 target) { super(target); } 
    public dataReceived(Data d) { getTarget().dataReceived2(d); } 
} 

Ahora, con esto en su lugar, podemos hacer algo como esto:

List<DataReceiver> dataReceivers = new ArrayList<DataReceiver>(); 
dataReceivers.add(new IF1Adapter(someIf1Implementation)); 
dataReceivers.add(new IF2Adapter(someIf2Implementation)); 
fetchData(dataReceivers); 

public void fetchData(Collection<DataReceiver> receivers) { 

    try { 
    Data d = getSomeData(); 
    for (DataReceiver dr : receivers) { 
     dr.dataReceived(d); 
    } 
    } 
    catch (Exception e) { 
    for (DataReceiver dr : receivers) { 
     dr.onError(e.getMessage()); 
    } 
    } 
} 

Hay otros patrones que pueden ser aplicables en función de sus necesidades exactas como visitantes o tal vez una cadena de de tipo de responsabilidad en el que encadena sus receptores en una construcción de tipo lista enlazada y cada uno llama al siguiente en un constructo recursivo - esto sería bueno ya que fetchData no necesitaría saber que está obteniendo una colección, simplemente se pone una referencia al adaptador superior en la cadena. Entonces, AbstractIFAdapter tendría una referencia a otra AbstractIFAdapter, llamémosla next, y si la referencia no era nula, llamaría next.dataReceived(d) en su propio método dataReceived. Idea similar a ServletFilter s donde cada filtro obtiene el ServletRequest y luego llama al chain.doFilter(request,response).

+0

Muy útil respuesta. ¡Terminé con una versión de tu primera sugerencia modificada para mis necesidades! – monoceres

1

Puede utilizar la biblioteca de Google guayaba, ver this answer

+0

Preferiría no utilizar una biblioteca tan pesada en este proyecto. – monoceres

Cuestiones relacionadas