2013-12-14 7 views
20

I Retrofit und in jeder Aufgabe verwende ich so etwas wie dies zu tun:Gibt es eine Möglichkeit Builder Code wiederverwenden für die Nachrüstung

public class MyTask extends AsyncTask<String, String, String> { 

    private void someMethod() { 
     final RestAdapter restAdapter = new RestAdapter.Builder() 
      .setServer("http://10.0.2.2:8080") 
      .build(); 
     final MyTaskService apiManager = restAdapter.create(MyTaskService.class); 
    } 

    // ... 

} 

Was ist ein guter Weg, um diesen Code DRY zu machen?

+0

Wo hast du 'RestAdapter':

public class ApiManager { public interface GitHubService { @GET("/users/{user}/repos") List<Repo> listRepos(@Path("user") String user); } private static final String API_URL = "https://api.github.com"; private static final RestAdapter REST_ADAPTER = new RestAdapter.Builder() .setEndpoint(API_URL) .setLogLevel(LogLevel.FULL) .build(); private static final GitHubService GIT_HUB_SERVICE = REST_ADAPTER.create(GitHubService.class); public static GitHubService getService() { return GIT_HUB_SERVICE; } } 

Sie den Dienst in diesem Beispiel, wie so verwenden kann? Könnte ich es wissen? – Geros

+0

Was meinst du mit DRY? – Husyn

+1

Sie könnten einfach einige Vererbungskonzepte verwenden –

Antwort

5

zuerst erklären Sie Eltern-Klasse mit allen gängigen Verhalten

public abstract class MyAbstractTask extends AsyncTask<String, String, String> { 

protected void someMethod() { //note that i change private to protected 
    final RestAdapter restAdapter = new RestAdapter.Builder().setServer("http://10.0.2.2:8080").build(); 
    final MyTaskService apiManager = restAdapter.create(MyTaskService.class); 
} 

} 

dann, können Sie es mit jeder Aufgabe erweitern

public class MyTask extends MyAbstractTask { 

//your someMethod() is available from everywhere in your class 

} 

public class MyOtherTask extends MyAbstractTask { 

//your someMethod() is available from everywhere in your class 

} 

aber ich weiß nicht, wo Sie restAdapter und apiManager verwenden , und wenn die tatsächlich einmal pro Aufgabe erstellt werden müssen, da Sie wahrscheinlich außerhalb dieser Aufgaben erstellen können.

Wenn Sie sie außerhalb erstellen, und dann müssen Sie etwas in Ihrer Aufgabe verwenden, ist es auch gut, das Muster Dependency_injection zu berücksichtigen.


Außerdem sollten Sie Hardcoding-Werte in Ihren Klassen, wie http://10.0.2.2:8080

sollten Sie verwenden mindestens ein final static final String server= "http://10.0.2.2:8080" und verwenden Sie dann das, oder besser, verwenden Sie einen Setter oder den Konstruktor in der innersten Klasse vermeiden und setzen Sie die Werte von der Aktivität oder dem Hauptcontroller.

42

Sowohl die RestAdapter als auch die generierte Instanz Ihrer Dienste (MyTaskService in diesem Fall) sind extrem teure Objekte und sollten als Singletons verwendet werden.

Dies bedeutet, dass Sie immer nur einmal restAdapter.create aufrufen und dieselbe Instanz von MyTaskService jedes Mal erneut verwenden sollten, wenn Sie interagieren müssen.

Ich kann das nicht genug betonen.

Sie können das normale Singleton-Muster verwenden, um sicherzustellen, dass es immer nur eine einzige Instanz dieser Objekte gibt, die Sie überall verwenden. Ein Dependency-Injection-Framework wäre auch etwas, das zur Verwaltung dieser Instanzen verwendet werden könnte, wäre aber etwas übertrieben, wenn Sie es nicht bereits nutzen.

+1

Vielen Dank für Ihre Antwort. Ich habe den Create-Aufruf, der die Proxy-Klasse in Retrofit verwendet, zum Erstellen der Anforderungsinstanz mithilfe von 'newProxyInstance' bewertet. Ich habe dies auf einem Gerät (Nexus 5 mit 4.4) für eine Schnittstelle getan, die zwischen 1 und 4 Service-Methoden unterschiedlicher Komplexität definiert. Es dauerte 4-5 Millisekunden beim ersten Mal und 0,3 bis 0.5 Millisekunden jede einzelne nachfolgende Zeit im selben Lauf. Vielleicht verstehe ich das nicht, aber gibt es einen Grund, warum Sie das für teuer halten? Bettet Android die Erstellung auch nach dem ersten Mal? Nur versuchen, etwas Klarheit zu bekommen, das ist alles – Rickster

+1

Es ist nicht teuer in Bezug auf wie schnell es laufen wird, sondern in Bezug auf Speicher. Jeder RestAdapter benötigt eine beträchtliche Menge an Speicher, weshalb ein Singleton hier wünschenswert wäre, da dann immer nur eine Kopie im Speicher ist. Image Sie machen 10, geschweige denn 100 von Anfragen, jedes mit seinem eigenen RestAdapter. Der Garbage Collector kann sie nicht schnell genug bereinigen, und Sie können sehr leicht aus dem Speicher kommen. Android speichert dies nicht, aber Sie können es sehr leicht mit [Singletons] (http://www.javaworld.com/article/2073352/core-java/simply-singleton.html) machen. – yiati

+0

@JakeWharton Ist das immer noch so? Ich habe gerade 100 RestAdapters ohne signifikanten Speicherzuwachs erstellt. – Eugene

44

Wie Jake sagte, sollten Sie die singleton pattern verwenden, um sicherzustellen, dass immer dieselbe Instanz verwendet wird.

Hier ist ein Beispiel:

ApiManager.getService().listRepos(...); 
+1

@Gautham für jede Anfrage muss ich einen anderen Konverter verwenden.wie als Singleton zu verwenden? – Asthme

+0

@Asthme Warum möchten Sie für jede Anfrage eine andere addConverterFactory verwenden? – Lobato

Verwandte Themen