我的天气应用程序收到响应但不显示
My Weather app gets response but doesn't display it
我正在开发一个天气应用程序,目前正在开发一个搜索城市按钮。我的主要目标是启用按钮搜索并显示在 edittext 上键入的任何城市数据。
我创建了一个编辑文本和搜索按钮,我还将它们与我解析的改进 classes 连接起来。
我按照这个 youtube 教程寻求帮助 https://www.youtube.com/watch?v=SrVY2la7lCI
也从这个 post 得到了一点帮助。他们都能够显示搜索到的任何城市的天气数据。
但是如果我在我的 ApiInterface weather?appid=9c547bfc852923c3b30d0d62a5ae35e8&units=metric
上使用这个地址(他们使用的),它 returns 会出现以下错误:
java.lang.NullPointerException: Attempt to invoke virtual method 'com.viz.realtimeweather.Retrofit.Main com.com.viz.realtimeweather.Retrofit.Example.getMain()' on a null object reference
at com.viz.realtimeweather.FirstFragment.onResponse(FirstFragment.java:109)
at retrofit2.DefaultCallAdapterFactory$ExecutorCallbackCall.lambda$onResponse[=10=]$DefaultCallAdapterFactory$ExecutorCallbackCall(DefaultCallAdapterFactory.java:89)
at retrofit2.-$$Lambda$DefaultCallAdapterFactory$ExecutorCallbackCallwC8FyV4pyjrzrYL5U0mlYiviZw.run(Unknown Source:6)
at android.os.Handler.handleCallback(Handler.java:873)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6819)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:497)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:912)
不显示任何数据。
然后当我向它添加查询时。即 q=london
,它没有返回任何错误,但仍然没有显示任何数据。我觉得问题出在其他地方,但我不知道确切的位置。此外,这也不是解决方案,因为我需要启用该应用程序来搜索任何位置,而不仅仅是特定的城市。
到目前为止,我有:
检查我所有已解析的网络 classes 是否有错误,但发现 none
检查了我的 ApiClient
和 ApiInterface
class 是否有任何错误的网络地址,但发现 none
在我的ApiInterface地址上添加了q=london
,但它不显示任何数据,也不搜索其他城市数据
检查此站点是否有任何与天气相关的问题,但发现 none。
使用 https://whosebug.com/help/minimal-reproducible-example,我将分享我的代码以寻求帮助。
我正在使用 OpenWeatherMap API 格式:
{
"coord":{
"lon":-122.08,
"lat":37.39
},
"weather":[
{
"id":800,
"main":"Clear",
"description":"clear sky",
"icon":"01d"
}
],
"base":"stations",
"main":{
"temp":282.55,
"feels_like":281.86,
"temp_min":280.37,
"temp_max":284.26,
"pressure":1023,
"humidity":100
},
"visibility":16093,
"wind":{
"speed":1.5,
"deg":350
},
"clouds":{
"all":1
},
"dt":1560350645,
"sys":{
"type":1,
"id":5122,
"message":0.0139,
"country":"US",
"sunrise":1560343627,
"sunset":1560396563
},
"timezone":-25200,
"id":420006353,
"name":"Mountain View",
"cod":200
}
我的 JSON 回复(当我不添加查询时):
{
"cod":"400",
"message":"Nothing to geocode"
}
HomeActivity.java:
public class HomeActivity extends AppCompatActivity {
// User current time
TextView time_field;
ImageView Search;
EditText textfield;
ConstraintLayout constraintLayout;
// For scheduling background image change
public static int count=0;
int[] drawable =new int[]{R.drawable.dubai,R.drawable.central_bank_of_nigeria,R.drawable.eiffel_tower,R.drawable.hong_kong,R.drawable.statue_of_liberty};
Timer _t;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
time_field = findViewById(R.id.textView9);
Search = findViewById(R.id.imageView4);
textfield = findViewById(R.id.textfield);
BottomNavigationView bottomNavigationView = findViewById(R.id.bottomNavigationView);
final NavHostFragment navHostFragment = (NavHostFragment) getSupportFragmentManager().findFragmentById(R.id.fragment);
assert navHostFragment != null;
final NavController navController = navHostFragment.getNavController();
NavigationUI.setupWithNavController(bottomNavigationView, navController);
Search.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
getWeatherData(textfield.getText().toString().trim());
int id = Objects.requireNonNull(navController.getCurrentDestination()).getId();
navController.popBackStack();
navController.navigate(id);
constraintLayout = findViewById(R.id.layout);
constraintLayout.setBackgroundResource(R.drawable.dubai);
_t = new Timer();
_t.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
// run on ui thread
runOnUiThread(() -> {
if (count < drawable.length) {
constraintLayout.setBackgroundResource(drawable[count]);
count = (count + 1) % drawable.length;
}
});
}
}, 5000, 5000);
}
private void getWeatherData(String name) {
ApiInterface apiInterface = ApiClient.getClient().create(ApiInterface.class);
Call<Example> call = apiInterface.getWeatherData(name);
call.enqueue(new Callback<Example>() {
@Override
public void onResponse(@NotNull Call<Example> call, @NotNull Response<Example> response) {
assert response.body() != null;
time_field.setText(String.valueOf(response.body().getDt()));
}
@Override
public void onFailure(@NotNull Call<Example> call, @NotNull Throwable t) {
t.printStackTrace();
}
});
}
});
}
}
第一个 Fragment.java:
public class FirstFragment extends Fragment {
// User current time, current temperature, current condition, sunrise, sunset, temperature, pressure, humidity, wind_speed, visibility, clouds
TextView current_temp, current_output, rise_time, set_time, temp_out, Press_out, Humid_out, Ws_out, Visi_out, Cloud_out;
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private static final String ARG_PARAM1 = "param1";
private static final String ARG_PARAM2 = "param2";
// TODO: Rename and change types of parameters
private String mParam1;
private String mParam2;
public FirstFragment() {
// Required empty public constructor
}
/**
* Use this factory method to create a new instance of
* this fragment using the provided parameters.
*
* @param param1 Parameter 1.
* @param param2 Parameter 2.
* @return A new instance of fragment SecondFragment.
*/
// TODO: Rename and change types and number of parameters
public static FirstFragment newInstance(String param1, String param2) {
FirstFragment fragment = new FirstFragment();
Bundle args = new Bundle();
args.putString(ARG_PARAM1, param1);
args.putString(ARG_PARAM2, param2);
fragment.setArguments(args);
return fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mParam1 = getArguments().getString(ARG_PARAM1);
mParam2 = getArguments().getString(ARG_PARAM2);
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View rootView = inflater.inflate(R.layout.fragment_first, container, false);
// For displaying weather data
current_temp = rootView.findViewById(R.id.textView10);
current_output = rootView.findViewById(R.id.textView11);
rise_time = rootView.findViewById(R.id.textView25);
set_time = rootView.findViewById(R.id.textView26);
temp_out = rootView.findViewById(R.id.textView28);
Press_out = rootView.findViewById(R.id.textView29);
Humid_out = rootView.findViewById(R.id.textView30);
Ws_out = rootView.findViewById(R.id.textView33);
Visi_out = rootView.findViewById(R.id.textView34);
Cloud_out = rootView.findViewById(R.id.textView35);
// Use activity data
FragmentActivity fa = getActivity();
assert fa != null;
EditText textfield = fa.findViewById(R.id.textfield);
getWeatherData(textfield.getText().toString().trim());
return rootView;
}
private void getWeatherData(String name) {
ApiInterface apiInterface = ApiClient.getClient().create(ApiInterface.class);
Call<Example> call = apiInterface.getWeatherData(name);
call.enqueue(new Callback<Example>() {
@Override
public void onResponse(@NotNull Call<Example> call, @NotNull Response<Example> response) {
assert response.body() !=null;
current_temp.setText(response.body().getMain().getTemp() + " ℃");
current_output.setText(response.body().getWeatherList().get(0).getDescription());
rise_time.setText(response.body().getSys().getSunrise() + " ");
set_time.setText(response.body().getSys().getSunset() + " ");
temp_out.setText(response.body().getMain().getTemp() + " ℃");
Press_out.setText(response.body().getMain().getPressure() + " hpa");
Humid_out.setText(response.body().getMain().getHumidity() + " %");
Ws_out.setText(response.body().getWind().getSpeed() + " Km/h");
Visi_out.setText(response.body().getVisibility() + " m");
Cloud_out.setText(response.body().getClouds().getAll()+ " %");
}
@Override
public void onFailure(@NotNull Call<Example> call, @NotNull Throwable t) {
t.printStackTrace();
}
});
}
}
ApiClient.java:
public class ApiClient {
private static Retrofit retrofit = null;
public static Retrofit getClient(){ //creating object
if (retrofit == null) {
retrofit = new Retrofit.Builder()
.baseUrl("http://api.openweathermap.org/data/2.5/")
.addConverterFactory(GsonConverterFactory.create())
.build();
}
return retrofit;
}
}
ApiInterface.java:
public interface ApiInterface {
@GET("weather?appid=9c547bfc852923c3b30d0d62a5ae35e8&units=metric")
Call<Example> getWeatherData(@Query("q") String name);
}
Example.java:
public class Example {
@SerializedName("main")
private Main main;
@SerializedName("weather")
private List<Weather> weatherList;
@SerializedName("visibility")
private Visibility visibility;
@SerializedName("wind")
private Wind wind;
@SerializedName("clouds")
private Clouds clouds;
@SerializedName("dt")
private Dt dt;
@SerializedName("sys")
private Sys sys;
@SerializedName("name")
private Name name;
public Main getMain() {
return main;
}
public void setMain(Main main) {
this.main = main;
}
public List<Weather> getWeatherList() {
return weatherList;
}
public void setWeatherList(List<Weather> weatherList) {
this.weatherList = weatherList;
}
public Visibility getVisibility() {
return visibility;
}
public void setVisibility(Visibility visibility) {
this.visibility = visibility;
}
public Wind getWind() {
return wind;
}
public void setWind(Wind wind) {
this.wind = wind;
}
public Clouds getClouds() {
return clouds;
}
public void setClouds(Clouds clouds) {
this.clouds = clouds;
}
public Dt getDt() {
return dt;
}
public void setDt(Dt dt) {
this.dt = dt;
}
public Sys getSys() {
return sys;
}
public void setSys(Sys sys) {
this.sys = sys;
}
public Name getName() {
return name;
}
public void setName(Name name) {
this.name = name;
}
}
Main.java:
public class Main {
@SerializedName("temp")
String temp;
@SerializedName("pressure")
String pressure;
@SerializedName("humidity")
String humidity;
public String getTemp() {
return temp;
}
public void setTemp(String temp) {
this.temp = temp;
}
public String getPressure() {
return pressure;
}
public void setPressure(String pressure) {
this.pressure = pressure;
}
public String getHumidity() {
return humidity;
}
public void setHumidity(String humidity) {
this.humidity = humidity;
}
}
编辑
dt.java:
public class Dt {
@SerializedName("dt")
@Expose
private PrettyTime dt;
public PrettyTime getDt() {
return dt;
}
public void setDt(PrettyTime dt) {
this.dt = dt;
}
}
问题是您通过调用 http://api.openweathermap.org/data/2.5/weather?appid=9c547bfc852923c3b30d0d62a5ae35e8&units=metric
收到 400 Bad Request
甚至
任何不属于 [200; 300[
范围的改造都会被认为是错误,不会给你一个 body()
,因此是空指针,因为 body()
是空的。另一方面,errorBody()
将有您想要的字符串。
要使用错误主体,您可以简单地执行 errorBody().string()
但要小心,因为它表现为一个流并且只能使用一次。
至于您的请求为何下降,这似乎是因为您缺少一些查询参数以允许给定坐标的开放天气 api 至 return 天气。添加一个简单的 q=lisbon
似乎可以解决问题:
将 return 200 OK
和改造 body()
方法将 return 一些东西。也许你发送的是空的?
经过discussion and also from my comments to the question the model mapping the JSON response was not correct and all that was required was to map the response正确到Java模型。
我正在开发一个天气应用程序,目前正在开发一个搜索城市按钮。我的主要目标是启用按钮搜索并显示在 edittext 上键入的任何城市数据。
我创建了一个编辑文本和搜索按钮,我还将它们与我解析的改进 classes 连接起来。
我按照这个 youtube 教程寻求帮助 https://www.youtube.com/watch?v=SrVY2la7lCI
也从这个 post
但是如果我在我的 ApiInterface weather?appid=9c547bfc852923c3b30d0d62a5ae35e8&units=metric
上使用这个地址(他们使用的),它 returns 会出现以下错误:
java.lang.NullPointerException: Attempt to invoke virtual method 'com.viz.realtimeweather.Retrofit.Main com.com.viz.realtimeweather.Retrofit.Example.getMain()' on a null object reference
at com.viz.realtimeweather.FirstFragment.onResponse(FirstFragment.java:109)
at retrofit2.DefaultCallAdapterFactory$ExecutorCallbackCall.lambda$onResponse[=10=]$DefaultCallAdapterFactory$ExecutorCallbackCall(DefaultCallAdapterFactory.java:89)
at retrofit2.-$$Lambda$DefaultCallAdapterFactory$ExecutorCallbackCallwC8FyV4pyjrzrYL5U0mlYiviZw.run(Unknown Source:6)
at android.os.Handler.handleCallback(Handler.java:873)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6819)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:497)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:912)
不显示任何数据。
然后当我向它添加查询时。即 q=london
,它没有返回任何错误,但仍然没有显示任何数据。我觉得问题出在其他地方,但我不知道确切的位置。此外,这也不是解决方案,因为我需要启用该应用程序来搜索任何位置,而不仅仅是特定的城市。
到目前为止,我有:
检查我所有已解析的网络 classes 是否有错误,但发现 none
检查了我的
ApiClient
和ApiInterface
class 是否有任何错误的网络地址,但发现 none在我的ApiInterface地址上添加了
q=london
,但它不显示任何数据,也不搜索其他城市数据检查此站点是否有任何与天气相关的问题,但发现 none。
使用 https://whosebug.com/help/minimal-reproducible-example,我将分享我的代码以寻求帮助。
我正在使用 OpenWeatherMap API 格式:
{
"coord":{
"lon":-122.08,
"lat":37.39
},
"weather":[
{
"id":800,
"main":"Clear",
"description":"clear sky",
"icon":"01d"
}
],
"base":"stations",
"main":{
"temp":282.55,
"feels_like":281.86,
"temp_min":280.37,
"temp_max":284.26,
"pressure":1023,
"humidity":100
},
"visibility":16093,
"wind":{
"speed":1.5,
"deg":350
},
"clouds":{
"all":1
},
"dt":1560350645,
"sys":{
"type":1,
"id":5122,
"message":0.0139,
"country":"US",
"sunrise":1560343627,
"sunset":1560396563
},
"timezone":-25200,
"id":420006353,
"name":"Mountain View",
"cod":200
}
我的 JSON 回复(当我不添加查询时):
{
"cod":"400",
"message":"Nothing to geocode"
}
HomeActivity.java:
public class HomeActivity extends AppCompatActivity {
// User current time
TextView time_field;
ImageView Search;
EditText textfield;
ConstraintLayout constraintLayout;
// For scheduling background image change
public static int count=0;
int[] drawable =new int[]{R.drawable.dubai,R.drawable.central_bank_of_nigeria,R.drawable.eiffel_tower,R.drawable.hong_kong,R.drawable.statue_of_liberty};
Timer _t;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_home);
time_field = findViewById(R.id.textView9);
Search = findViewById(R.id.imageView4);
textfield = findViewById(R.id.textfield);
BottomNavigationView bottomNavigationView = findViewById(R.id.bottomNavigationView);
final NavHostFragment navHostFragment = (NavHostFragment) getSupportFragmentManager().findFragmentById(R.id.fragment);
assert navHostFragment != null;
final NavController navController = navHostFragment.getNavController();
NavigationUI.setupWithNavController(bottomNavigationView, navController);
Search.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
getWeatherData(textfield.getText().toString().trim());
int id = Objects.requireNonNull(navController.getCurrentDestination()).getId();
navController.popBackStack();
navController.navigate(id);
constraintLayout = findViewById(R.id.layout);
constraintLayout.setBackgroundResource(R.drawable.dubai);
_t = new Timer();
_t.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
// run on ui thread
runOnUiThread(() -> {
if (count < drawable.length) {
constraintLayout.setBackgroundResource(drawable[count]);
count = (count + 1) % drawable.length;
}
});
}
}, 5000, 5000);
}
private void getWeatherData(String name) {
ApiInterface apiInterface = ApiClient.getClient().create(ApiInterface.class);
Call<Example> call = apiInterface.getWeatherData(name);
call.enqueue(new Callback<Example>() {
@Override
public void onResponse(@NotNull Call<Example> call, @NotNull Response<Example> response) {
assert response.body() != null;
time_field.setText(String.valueOf(response.body().getDt()));
}
@Override
public void onFailure(@NotNull Call<Example> call, @NotNull Throwable t) {
t.printStackTrace();
}
});
}
});
}
}
第一个 Fragment.java:
public class FirstFragment extends Fragment {
// User current time, current temperature, current condition, sunrise, sunset, temperature, pressure, humidity, wind_speed, visibility, clouds
TextView current_temp, current_output, rise_time, set_time, temp_out, Press_out, Humid_out, Ws_out, Visi_out, Cloud_out;
// TODO: Rename parameter arguments, choose names that match
// the fragment initialization parameters, e.g. ARG_ITEM_NUMBER
private static final String ARG_PARAM1 = "param1";
private static final String ARG_PARAM2 = "param2";
// TODO: Rename and change types of parameters
private String mParam1;
private String mParam2;
public FirstFragment() {
// Required empty public constructor
}
/**
* Use this factory method to create a new instance of
* this fragment using the provided parameters.
*
* @param param1 Parameter 1.
* @param param2 Parameter 2.
* @return A new instance of fragment SecondFragment.
*/
// TODO: Rename and change types and number of parameters
public static FirstFragment newInstance(String param1, String param2) {
FirstFragment fragment = new FirstFragment();
Bundle args = new Bundle();
args.putString(ARG_PARAM1, param1);
args.putString(ARG_PARAM2, param2);
fragment.setArguments(args);
return fragment;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mParam1 = getArguments().getString(ARG_PARAM1);
mParam2 = getArguments().getString(ARG_PARAM2);
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
View rootView = inflater.inflate(R.layout.fragment_first, container, false);
// For displaying weather data
current_temp = rootView.findViewById(R.id.textView10);
current_output = rootView.findViewById(R.id.textView11);
rise_time = rootView.findViewById(R.id.textView25);
set_time = rootView.findViewById(R.id.textView26);
temp_out = rootView.findViewById(R.id.textView28);
Press_out = rootView.findViewById(R.id.textView29);
Humid_out = rootView.findViewById(R.id.textView30);
Ws_out = rootView.findViewById(R.id.textView33);
Visi_out = rootView.findViewById(R.id.textView34);
Cloud_out = rootView.findViewById(R.id.textView35);
// Use activity data
FragmentActivity fa = getActivity();
assert fa != null;
EditText textfield = fa.findViewById(R.id.textfield);
getWeatherData(textfield.getText().toString().trim());
return rootView;
}
private void getWeatherData(String name) {
ApiInterface apiInterface = ApiClient.getClient().create(ApiInterface.class);
Call<Example> call = apiInterface.getWeatherData(name);
call.enqueue(new Callback<Example>() {
@Override
public void onResponse(@NotNull Call<Example> call, @NotNull Response<Example> response) {
assert response.body() !=null;
current_temp.setText(response.body().getMain().getTemp() + " ℃");
current_output.setText(response.body().getWeatherList().get(0).getDescription());
rise_time.setText(response.body().getSys().getSunrise() + " ");
set_time.setText(response.body().getSys().getSunset() + " ");
temp_out.setText(response.body().getMain().getTemp() + " ℃");
Press_out.setText(response.body().getMain().getPressure() + " hpa");
Humid_out.setText(response.body().getMain().getHumidity() + " %");
Ws_out.setText(response.body().getWind().getSpeed() + " Km/h");
Visi_out.setText(response.body().getVisibility() + " m");
Cloud_out.setText(response.body().getClouds().getAll()+ " %");
}
@Override
public void onFailure(@NotNull Call<Example> call, @NotNull Throwable t) {
t.printStackTrace();
}
});
}
}
ApiClient.java:
public class ApiClient {
private static Retrofit retrofit = null;
public static Retrofit getClient(){ //creating object
if (retrofit == null) {
retrofit = new Retrofit.Builder()
.baseUrl("http://api.openweathermap.org/data/2.5/")
.addConverterFactory(GsonConverterFactory.create())
.build();
}
return retrofit;
}
}
ApiInterface.java:
public interface ApiInterface {
@GET("weather?appid=9c547bfc852923c3b30d0d62a5ae35e8&units=metric")
Call<Example> getWeatherData(@Query("q") String name);
}
Example.java:
public class Example {
@SerializedName("main")
private Main main;
@SerializedName("weather")
private List<Weather> weatherList;
@SerializedName("visibility")
private Visibility visibility;
@SerializedName("wind")
private Wind wind;
@SerializedName("clouds")
private Clouds clouds;
@SerializedName("dt")
private Dt dt;
@SerializedName("sys")
private Sys sys;
@SerializedName("name")
private Name name;
public Main getMain() {
return main;
}
public void setMain(Main main) {
this.main = main;
}
public List<Weather> getWeatherList() {
return weatherList;
}
public void setWeatherList(List<Weather> weatherList) {
this.weatherList = weatherList;
}
public Visibility getVisibility() {
return visibility;
}
public void setVisibility(Visibility visibility) {
this.visibility = visibility;
}
public Wind getWind() {
return wind;
}
public void setWind(Wind wind) {
this.wind = wind;
}
public Clouds getClouds() {
return clouds;
}
public void setClouds(Clouds clouds) {
this.clouds = clouds;
}
public Dt getDt() {
return dt;
}
public void setDt(Dt dt) {
this.dt = dt;
}
public Sys getSys() {
return sys;
}
public void setSys(Sys sys) {
this.sys = sys;
}
public Name getName() {
return name;
}
public void setName(Name name) {
this.name = name;
}
}
Main.java:
public class Main {
@SerializedName("temp")
String temp;
@SerializedName("pressure")
String pressure;
@SerializedName("humidity")
String humidity;
public String getTemp() {
return temp;
}
public void setTemp(String temp) {
this.temp = temp;
}
public String getPressure() {
return pressure;
}
public void setPressure(String pressure) {
this.pressure = pressure;
}
public String getHumidity() {
return humidity;
}
public void setHumidity(String humidity) {
this.humidity = humidity;
}
}
编辑
dt.java:
public class Dt {
@SerializedName("dt")
@Expose
private PrettyTime dt;
public PrettyTime getDt() {
return dt;
}
public void setDt(PrettyTime dt) {
this.dt = dt;
}
}
问题是您通过调用 http://api.openweathermap.org/data/2.5/weather?appid=9c547bfc852923c3b30d0d62a5ae35e8&units=metric
收到400 Bad Request
甚至
任何不属于 [200; 300[
范围的改造都会被认为是错误,不会给你一个 body()
,因此是空指针,因为 body()
是空的。另一方面,errorBody()
将有您想要的字符串。
要使用错误主体,您可以简单地执行 errorBody().string()
但要小心,因为它表现为一个流并且只能使用一次。
至于您的请求为何下降,这似乎是因为您缺少一些查询参数以允许给定坐标的开放天气 api 至 return 天气。添加一个简单的 q=lisbon
似乎可以解决问题:
将 return 200 OK
和改造 body()
方法将 return 一些东西。也许你发送的是空的?
经过discussion and also from my comments to the question the model mapping the JSON response was not correct and all that was required was to map the response正确到Java模型。