Android how to get response string from Callback using OkHttp?

13,240

Solution 1

I think what you want to do is something like this:

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 the above activity we implement Callback and then when we create the okhttp request, we pass it an instance of ourself (this) and that way we can get oktthp to call back the class, we could have done an inner class just as easily but this reduces the # of classes we have to make. I used a button click to illustrate when the Http call is made but that could be some other time, for instance it could happen when the screen is first created (in onCreate). Be careful though of screen rotations. Also this assumes that the callback is done on the main thread which I think it would be but I'm not positive as I use okttp in a different way than you. If it does not return the results on the response on the main thread then you can call runOnUiThread() and pass it a Runnable that does the work of updating the views.

Solution 2

If you move the responseString declaration to be an instance variable then you will be able to assign its value in the onResponse method of your Callback.

public class MyClass {

    private String responseString; 

    // your class implementation

}

I have modified the code you posted with the necessary changes below:

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

Solution 3

First answer is close, but you cannot assign final variable in method onResponse. Workaround is to type final String[] responseString = new String[1]; and assign responseString[0] = response.body().string();

Share:
13,240
tm-null
Author by

tm-null

Updated on June 22, 2022

Comments

  • tm-null
    tm-null almost 2 years

    This is my code:

        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 the above code, I want to store the value of response.body().string() from the onResponse() method in the variable responseString, however I can't access it.

    • Matt Wolfe
      Matt Wolfe almost 9 years
      I'm kind of confused what you are trying to do here. If this code exists in a local function then what good does it do to use an asynchronous callback and store a variable declared in the calling function? You wouldn't be able to use that anyways unless you block first. You could store the response in a class instance variable instead and that would work fine. More than likely though you're going about this the wrong way.
    • tm-null
      tm-null almost 9 years
      @MattWolfe you are probably right, I am new to Android development. What I am trying to do is get some data like this link, save it in a variable, parse it and then display it on the screen using a View. Would storing the data in an instance variable be the right way to do this or is there another way? Thank you.
    • Matt Wolfe
      Matt Wolfe almost 9 years
      I would just have your activity/fragment implement Callback: Then do: okHttpClient.newCall(request).enqueue(this); Then in your onResponse parse it and you can display the results to screen.
  • tm-null
    tm-null almost 9 years
    Unfortunately I can't change the value of responseString inside onResponse since it is final
  • tm-null
    tm-null almost 9 years
    After changing my code, gist.github.com/taimoor-ahmad/ef9515751294d80d460e I get java.lang.NullPointerException: println needs a message when trying to use the value of responseString[0] in my Log
  • Tomek
    Tomek almost 9 years
    becouse code in onResponse was not yet called back, you have to print it after callback execution
  • Andrea Thacker
    Andrea Thacker almost 9 years
    You are perfectly correct, sorry for the mistake. I have modified my code but if it is no longer useful I will remove it.
  • tm-null
    tm-null almost 9 years
    Thank you. It turns out that code does work, however it takes a while for the value of responseString to be updated.
  • Andrea Thacker
    Andrea Thacker almost 9 years
    Yes, that is because it happens asynchronously and depends on the response time of the network and the endpoint you are receiving data from. That will be the case for all applications that are receiving data from an internet source.
  • Pb Vignesh
    Pb Vignesh almost 7 years
    Can you post an example/link of something you would use, because the above method as you said would execute the network call every time on screen rotation right?
  • Matt Wolfe
    Matt Wolfe almost 7 years
    This is a common problem without a single or simple solution.
  • Matt Wolfe
    Matt Wolfe almost 7 years