英文:
OkHttp3 response.body().string() always returns empty
问题
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;
import org.jetbrains.annotations.NotNull;
import java.io.IOException;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.ResponseBody;
public class MainActivity extends AppCompatActivity {
TextView title;
TextView instructions;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
title = findViewById(R.id.titleView);
instructions = findViewById(R.id.instructionsView);
OkHttpClient client = new OkHttpClient();
String url = "https://spoonacular-recipe-food-nutrition-v1.p.rapidapi.com/recipes/findByIngredients?number=1&ranking=1&ignorePantry=false&ingredients=apple%252Csugar%252Csalt";
Request request = new Request.Builder()
.url(url)
.get()
.addHeader("x-rapidapi-host", "spoonacular-recipe-food-nutrition-v1.p.rapidapi.com")
.addHeader("x-rapidapi-key", "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")
.build();
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(@NotNull Call call, @NotNull IOException e) {
e.printStackTrace();
}
@Override
public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
if (response.isSuccessful()) {
String myResponse = response.body().string();
Log.i("string", myResponse);
}
}
});
}
}
The Log output for .toString(): 2020-05-04 19:55:51.801 9894-10024/com.example.testapi I/string: okhttp3.internal.http.RealResponseBody@6314479
The Log output for .string(): 2020-05-04 20:00:39.430 10118-10143/com.example.testapi I/string: []
I know about how OkHttp3 is trying to empty the backing resource as soon as the first .body() call is made, but it's still empty for me.
How can I fix this?
英文:
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;
import org.jetbrains.annotations.NotNull;
import java.io.IOException;
import java.io.Reader;
import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.ResponseBody;
public class MainActivity extends AppCompatActivity {
TextView title;
TextView instructions;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
title = findViewById(R.id.titleView);
instructions = findViewById(R.id.instructionsView);
OkHttpClient client = new OkHttpClient();
String url = "https://spoonacular-recipe-food-nutrition-v1.p.rapidapi.com/recipes/findByIngredients?number=1&ranking=1&ignorePantry=false&ingredients=apple%252Csugar%252Csalt";
Request request = new Request.Builder()
.url(url)
.get()
.addHeader("x-rapidapi-host", "spoonacular-recipe-food-nutrition-v1.p.rapidapi.com")
.addHeader("x-rapidapi-key", "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx")
.build();
client.newCall(request).enqueue(new Callback() {
@Override
public void onFailure(@NotNull Call call, @NotNull IOException e) {
e.printStackTrace();
}
@Override
public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
if (response.isSuccessful()) {
String myResponse = response.body().string();
Log.i("string", myResponse);
}
}
});
}
}
The Log output for .toString(): 2020-05-04 19:55:51.801 9894-10024/com.example.testapi I/string: okhttp3.internal.http.RealResponseBody@6314479
The Log output for .string(): 2020-05-04 20:00:39.430 10118-10143/com.example.testapi I/string: []
I know about how OkHttp3 is trying to empty the backing resource as soon as the first .body() call is made, but it's still empty for me.
How can I fix this?
答案1
得分: 0
调用response.body().string()
会消耗掉响应体 - 因此,您不能第二次调用它。在您片段之外的代码中,必须至少剩下一个response.body()
。
> 响应体只能被消耗一次。
https://square.github.io/okhttp/3.x/okhttp/index.html?okhttp3/ResponseBody.html
修复
在您的实现代码的某处,response.body()
已经被调用了一次。改用response.peekBody()
来替代。
解决方案是,如果您需要进一步处理它,可以将其存储在变量中。
@Override
public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
if (response.isSuccessful()) {
String myResponse = response.peekBody(99999L).string();
Log.i("string", myResponse);
}
}
英文:
Calling response.body().string()
consumes the body - therefore, you can't call it the second time. In the code outside of your snippet , there must be at least one response.body()
left.
> The response body can be consumed only once.
https://square.github.io/okhttp/3.x/okhttp/index.html?okhttp3/ResponseBody.html
Fix
Somewhere in your implementation code, response.body()
is already called once. Instead replace by response.peekBody()
.
The solution is to store it in a variable if you need it for further processing.
@Override
public void onResponse(@NotNull Call call, @NotNull Response response) throws IOException {
if (response.isSuccessful()) {
String myResponse = response.peekBody(99999L).string();
Log.i("string", myResponse);
}
}
专注分享java语言的经验与见解,让所有开发者获益!
评论