2012-04-03 3 views
5

Ich entwickle derzeit die Präsentationsschicht einer Android-App.Die eleganteste Lösung, um asynchrone Aufrufe in Java zu verketten?

Die api, die ich verwende sieht etwa so aus:

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) {} 

Das heißt; Zum Abrufen von Daten stellen Sie einen Empfänger zur Verfügung, der das Ergebnis der Operation irgendwann in der Zukunft empfängt.

Dies funktioniert sehr gut, wenn Sie nur eine Methode auf einmal aufrufen müssen, aber jetzt habe ich den Punkt erreicht, an dem ich mehr als 10 Methoden auf einmal aufrufen muss und sie nacheinander ausführen müssen.

Wie kann ich das auf flexible und elegante Weise lösen?

Danke!

Antwort

7

Lassen Sie mich sicher, ich verstehe .. Sie haben eine Reihe von Schnittstellen if1, if2 .. ifn und Sie wollen, dass sie alle Daten verarbeiten zu können, empfangen.

Zunächst einmal wäre es am besten, wenn if1, if2, etc alle die gleiche Schnittstelle mit zwei grundlegenden Methoden waren: public void dataReceived(Data d) und public void onError(String reason). Damit können Sie einfach einen List oder Collection Ihrer Empfänger an fetchData übergeben und es kann über die Sammlung iterieren und dataReceived(d) auf jedem anrufen.

Wenn, aus welchem ​​Grund auch immer, das nicht funktioniert, würde ich einen Adapter versuchen, um sie in eine ähnliche Schnittstelle für fetchData zu überreden. Zum Beispiel:

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

Jetzt mit, dass an Ort und Stelle, können wir so etwas tun:

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

Es gibt auch andere Muster, die je nach Ihren genauen Bedürfnissen wie Besuchern anwendbar sein können oder vielleicht eine Kette -Verantwortlichkeitstyp-Muster, in dem Sie Ihre Empfänger in einem Linked-List-Typ-Konstrukt verketten und jeder den nächsten in einem rekursiven Konstrukt aufruft - das wäre nett, da fetchData nicht wissen müsste, dass es eine Sammlung erhält, sondern nur ein Verweis auf die oben Adapter in der Kette. Also, AbstractIFAdapter hätte einen Verweis auf eine andere AbstractIFAdapter, nennen wir es next, und wenn die Referenz nicht null war, würde next.dataReceived(d) in seiner eigenen dataReceived Methode aufrufen. Ähnliche Idee wie s, wo jeder Filter bekommt ServletRequest und ruft dann chain.doFilter(request,response).

+0

Sehr hilfreiche Antwort. Ich habe eine Version Ihres ersten Vorschlags erhalten, die für meine Bedürfnisse modifiziert wurde! – monoceres

1

Sie können die Google Guava-Bibliothek verwenden, finden Sie this answer

+0

Ich würde lieber nicht eine solche schwere Bibliothek in diesem Projekt verwenden. – monoceres

Verwandte Themen