2015-06-30 9 views
6

Dies ist mein Code:Android Wie bekomme ich Antwort-String vom Rückruf mit OkHttp?

OkHttpClient okHttpClient = new OkHttpClient(); 

    Request request = new Request.Builder().url("http://publicobject.com/helloworld.txt").build(); 

    Callback callback = new Callback() { 
     @Override 
     public void onFailure(Request request, IOException e) { 

     } 

     @Override 
     public void onResponse(Response response) throws IOException { 

     } 
    }; 

    okHttpClient.newCall(request).enqueue(callback); 

    String responseString; 

In dem obigen Code, möchte ich den Wert von response.body speichern() string() aus der onResponse() -Methode in der Variablen responseString, aber ich kann‘. t darauf zugreifen.

+1

Ich bin irgendwie verwirrt, was Sie hier zu tun versuchen. Wenn dieser Code in einer lokalen Funktion vorhanden ist, was nutzt er dann, um einen asynchronen Callback zu verwenden und eine in der aufrufenden Funktion deklarierte Variable zu speichern? Sie könnten das sowieso nicht verwenden, wenn Sie nicht zuerst blocken. Sie könnten die Antwort stattdessen in einer Klasseninstanzvariablen speichern, und das würde gut funktionieren. Mehr als wahrscheinlich, obwohl Sie dies in die falsche Richtung gehen. –

+0

@MattWolfe Sie haben wahrscheinlich Recht, ich bin neu in Android-Entwicklung. Was ich versuche, ist, Daten wie diesen [link] (https://hacker-news.firebaseio.com/v0/topstories.json) zu bekommen, in einer Variablen zu speichern, zu parsen und dann auf dem Bildschirm anzuzeigen Verwenden einer Ansicht. Würden das Speichern der Daten in einer Instanzvariable der richtige Weg sein oder gibt es einen anderen Weg? Vielen Dank. –

+0

Ich würde nur Ihre Aktivität/Fragment implementieren Callback: Dann tun: okHttpClient.newCall (Anfrage) .enqueue (this); Dann in Ihrer onResponse analysieren Sie es und Sie können die Ergebnisse auf dem Bildschirm anzeigen. –

Antwort

4

Ich denke, was Sie so etwas wie dies tun möchte, ist:

public class MyActivity extends Activity implements Callback , View.OnClickListener { 


@Override 
public void onCreate(Bundle savedState) { 
    super.onCreate(savedState); 
    findViewById(R.id.DoHttp).setOnClickListener(this); 
} 

@Override 
public void onClick(View v) { 
    if (v.getId(() == R.id.DoHttp) { 

    OkHttpClient okHttpClient = new OkHttpClient(); 

    Request request = new Request.Builder().url("http://publicobject.com/helloworld.txt").build(); 
    okHttpClient.newCall(request).enqueue(this); 
    } 
} 


@Override 
public void onFailure(Request request, IOException e) { 
    //do something to indicate error 
} 

    @Override 
    public void onResponse(Response response) throws IOException { 
    if (response.isSuccessful()) { 
    parse(response.body().string()); 
    } 
    } 

    private void parse(String response) { 
    //do something with response 
    } 
} 

In der obigen Aktivität, die wir Rückruf implementieren und dann, wenn wir die okhttp Anfrage erstellen, übergeben wir es eine Instanz von uns selbst und auf diese Weise können wir oktthp dazu bringen, die Klasse zurückzurufen, wir hätten genauso leicht eine innere Klasse machen können, aber das reduziert die Anzahl der Klassen, die wir machen müssen. Ich habe einen Knopfklick benutzt, um zu illustrieren, wann der HTTP-Anruf gemacht wurde, aber das könnte ein anderer Zeitpunkt sein, zum Beispiel könnte es passieren, wenn der Bildschirm zum ersten Mal erstellt wird (in onCreate). Seien Sie vorsichtig bei der Bildschirmdrehung. Auch das setzt voraus, dass der Callback auf dem Hauptthread durchgeführt wird, was ich denke, aber ich bin nicht positiv, da ich oktp auf eine andere Weise nutze als du. Wenn es die Ergebnisse der Antwort im Hauptthread nicht zurückgibt, können Sie runOnUiThread() aufrufen und es an ein Runnable übergeben, das die Aktualisierung der Ansichten übernimmt.

+0

Können Sie ein Beispiel/Verbindung von etwas schreiben Sie würde verwenden, weil die oben genannte Methode, wie Sie sagten, den Netzwerkaufruf jedes Mal auf Bildschirmdrehung ausführen würde, richtig? –

+0

Dies ist ein häufiges Problem ohne eine einzige oder einfache Lösung. –

+0

https://medium.com/google-developers/making-loading-data-on-android-lifecycle-aware-897e12760832 –

2

Wenn Sie die responseString Deklaration als Instanzvariable verschieben, können Sie ihren Wert in der onResponse Methode Ihrer Callback zuweisen.

public class MyClass { 

    private String responseString; 

    // your class implementation 

} 

Ich habe den Code geändert Sie unten mit den notwendigen Änderungen posted:

OkHttpClient okHttpClient = new OkHttpClient(); 

Request request = new Request.Builder().url("http://publicobject.com/helloworld.txt").build(); 

Callback callback = new Callback() { 
    @Override 
    public void onFailure(Request request, IOException e) { 

    } 

    @Override 
    public void onResponse(Response response) throws IOException { 
     responseString = response.body().string(); 
    } 
}; 

okHttpClient.newCall(request).enqueue(callback); 
+0

Leider kann ich den Wert von responseString in onResponse nicht ändern, da es endgültig ist –

+0

Sie sind vollkommen richtig, sorry für den Fehler. Ich habe meinen Code geändert, aber wenn es nicht mehr nützlich ist, werde ich es entfernen. –

+0

Danke. Es stellt sich heraus, dass Code funktioniert, aber es dauert eine Weile, bis der Wert von responseString aktualisiert wird. –

1

erste Antwort der Nähe ist, aber man kann nicht endgültig Variable in der Methode onResponse zuweisen. Abhilfe ist final String[] responseString = new String[1]; eingeben und zuweisen responseString[0] = response.body().string();

+0

Nachdem ich meinen Code geändert habe, https://gist.github.com/taimoor-ahmad/ef9515751294d80d460e bekomme ich java.lang.Nullpointer: println braucht eine Nachricht, wenn der Wert von responseString zu verwenden versuchen [0] in meinem Log –

+0

becouse Code in onResponse noch nicht zurückgerufen, Sie haben es die Ausführung nach Rückruf drucken – Tomek

Verwandte Themen