如何解决如何阻止异常搜索不可用/无城市?
我有一个天气应用程序,可以搜索在 EditText
上输入的任何城市,而且效果很好。
但问题是,每当我搜索不可用的城市或将 "(my app) has stopped"
留空并单击搜索按钮时,应用程序就会崩溃并在我的手机上报告 EditText
(这只发生在我搜索不可用的城市时) /no city is searched),可以正确搜索任何有效的城市。
这是我的 Logcat 显示的内容(仅在搜索不可用城市时):
java.lang.NullPointerException: Attempt to invoke virtual method 'com.viz.lightweatherforecast.Retrofit.Example$Main com.viz.lightweatherforecast.Retrofit.Example.getMain()' on a null object reference
at com.viz.lightweatherforecast.FirstFragment$1.onResponse(FirstFragment.java:104)
at retrofit2.DefaultCallAdapterFactory$ExecutorCallbackCall$1.lambda$onResponse$0$DefaultCallAdapterFactory$ExecutorCallbackCall$1(DefaultCallAdapterFactory.java:89)
at retrofit2.-$$Lambda$DefaultCallAdapterFactory$ExecutorCallbackCall$1$3wC8FyV4pyjrzrYL5U0mlYiviZw.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)
和
java.lang.NullPointerException: Attempt to invoke virtual method 'com.viz.lightweatherforecast.first.PrettyTime com.viz.lightweatherforecast.Retrofit.Example.getDt()' on a null object reference
at com.viz.lightweatherforecast.Activity.HomeActivity$1$2.onResponse(HomeActivity.java:100)
at retrofit2.DefaultCallAdapterFactory$ExecutorCallbackCall$1.lambda$onResponse$0$DefaultCallAdapterFactory$ExecutorCallbackCall$1(DefaultCallAdapterFactory.java:89)
at retrofit2.-$$Lambda$DefaultCallAdapterFactory$ExecutorCallbackCall$1$3wC8FyV4pyjrzrYL5U0mlYiviZw.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)
未搜索城市时(EditText
为空)。
因此,我正在尝试停止对此负责的异常,并在搜索到不可用/未搜索到的城市时编写一个祝酒词/消息告诉用户“no city found
”。
请问我该怎么做?到目前为止,我已经尝试添加:
Log.d(TAG,"No City found");
在我的
@Override
public void onFailure(@NotNull Call<Example> call,@NotNull Throwable t) {
t.printstacktrace();
}
HomeActivity 中的方法,但它仍然崩溃。
这是我的具体代码:
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());
FirstFragment firstFragment = (FirstFragment) navHostFragment.getChildFragmentManager().getFragments().get(0);
firstFragment.getWeatherData(textfield.getText().toString().trim());
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("Last Updated:" + " " + response.body().getDt());
}
@Override
public void onFailure(@NotNull Call<Example> call,@NotNull Throwable t) {
t.printstacktrace();
}
});
}
});
}
}
FirstFragment.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);
return rootView;
}
public 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().getWeather().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();
}
});
}
}
编辑
示例.java:
public class Example {
@Serializedname("coord")
private Coord coord;
@Serializedname("weather")
private List<Weather> weather = null;
@Serializedname("base")
private String base;
@Serializedname("main")
private Main main;
@Serializedname("visibility")
private Integer visibility;
@Serializedname("wind")
private Wind wind;
@Serializedname("clouds")
private Clouds clouds;
@Serializedname("dt")
@Expose
private PrettyTime dt;
@Serializedname("sys")
private Sys sys;
@Serializedname("timezone")
private Integer timezone;
@Serializedname("id")
private Integer id;
@Serializedname("name")
private String name;
@Serializedname("cod")
private Integer cod;
public Coord getCoord() {
return coord;
}
public void setCoord(Coord coord) {
this.coord = coord;
}
public List<Weather> getWeather() {
return weather;
}
public void setWeather(List<Weather> weather) {
this.weather = weather;
}
public String getBase() {
return base;
}
public void setBase(String base) {
this.base = base;
}
public Main getMain() {
return main;
}
public void setMain(Main main) {
this.main = main;
}
public Integer getVisibility() {
return visibility;
}
public void setVisibility(Integer 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 PrettyTime getDt() {
return dt;
}
public void setDt(PrettyTime dt) {
this.dt = dt;
}
public Sys getSys() {
return sys;
}
public void setSys(Sys sys) {
this.sys = sys;
}
public Integer getTimezone() {
return timezone;
}
public void setTimezone(Integer timezone) {
this.timezone = timezone;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getCod() {
return cod;
}
public void setCod(Integer cod) {
this.cod = cod;
}
public class Clouds {
@Serializedname("all")
private Integer all;
public Integer getAll() {
return all;
}
public void setAll(Integer all) {
this.all = all;
}
}
public class Coord {
@Serializedname("lon")
private Double lon;
@Serializedname("lat")
private Double lat;
public Double getLon() {
return lon;
}
public void setLon(Double lon) {
this.lon = lon;
}
public Double getLat() {
return lat;
}
public void setLat(Double lat) {
this.lat = lat;
}
}
public class Main {
@Serializedname("temp")
private Double temp;
@Serializedname("feels_like")
private Double feelsLike;
@Serializedname("temp_min")
private Double tempMin;
@Serializedname("temp_max")
private Double tempMax;
@Serializedname("pressure")
private Integer pressure;
@Serializedname("humidity")
private Integer humidity;
public Double getTemp() {
return temp;
}
public void setTemp(Double temp) {
this.temp = temp;
}
public Double getFeelsLike() {
return feelsLike;
}
public void setFeelsLike(Double feelsLike) {
this.feelsLike = feelsLike;
}
public Double getTempMin() {
return tempMin;
}
public void setTempMin(Double tempMin) {
this.tempMin = tempMin;
}
public Double getTempMax() {
return tempMax;
}
public void setTempMax(Double tempMax) {
this.tempMax = tempMax;
}
public Integer getPressure() {
return pressure;
}
public void setPressure(Integer pressure) {
this.pressure = pressure;
}
public Integer getHumidity() {
return humidity;
}
public void setHumidity(Integer humidity) {
this.humidity = humidity;
}
}
public class Sys {
@Serializedname("type")
private Integer type;
@Serializedname("id")
private Integer id;
@Serializedname("country")
private String country;
@Serializedname("sunrise")
@Expose
private PrettyTime sunrise;
@Serializedname("sunset")
@Expose
private PrettyTime sunset;
public Integer getType() {
return type;
}
public void setType(Integer type) {
this.type = type;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
public PrettyTime getSunrise() {
return sunrise;
}
public void setSunrise(PrettyTime sunrise) {
this.sunrise = sunrise;
}
public PrettyTime getSunset() {
return sunset;
}
public void setSunset(PrettyTime sunset) {
this.sunset = sunset;
}
}
public class Weather {
@Serializedname("id")
private Integer id;
@Serializedname("main")
private String main;
@Serializedname("description")
private String description;
@Serializedname("icon")
private String icon;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getMain() {
return main;
}
public void setMain(String main) {
this.main = main;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getIcon() {
return icon;
}
public void setIcon(String icon) {
this.icon = icon;
}
}
public class Wind {
@Serializedname("speed")
private Double speed;
@Serializedname("deg")
private Integer deg;
@Serializedname("gust")
private Double gust;
public Double getSpeed() {
return speed;
}
public void setSpeed(Double speed) {
this.speed = speed;
}
public Integer getDeg() {
return deg;
}
public void setDeg(Integer deg) {
this.deg = deg;
}
public Double getGust() {
return gust;
}
public void setGust(Double gust) {
this.gust = gust;
}
}
}
解决方法
根据日志,您会收到带有正文的成功响应,但 getMain
返回 null
。
您可以通过在 getMain 周围添加一些空检查来防止这种情况发生。确保在 api 文档中检查 null 的可能性。
, public void onResponse(@NotNull Call<Example> call,@NotNull Response<Example> response) {
assert response.body() !=null;
if(response.body().getMain()==null && response.body().getWeather()!=null && all other field!=null){
yourErrorTextview.setText("No City found");
allOtherField.setText();
}
else if(response.body().getMain()!=null && response.body().getWeather()!=null && all other field!=null){
current_temp.setText(response.body().getMain().getTemp() + " ℃");
allOtherField.setText();
}}
,
正如 OP 所说的I just need the best method to handle the exceptions
让我举两个例子来说明您的情况,以避免崩溃并为 Activity 和 Fragment 显示 Toast。
- 尝试/捕捉
更新您的活动 onResponse
,如下所示。
public void onResponse(Call<Example> call,Response<Example> response) {
try {
time_field.setText("Last Updated:" + " " + response.body().getDt());
} catch (Exception e) {
time_field.setText("Last Updated: Unknown");
Log.e("TAG","No City found");
Toast.makeText(HomeActivity.this,"No City found",Toast.LENGTH_SHORT).show();
}
}
像下面这样更新你的片段`onResponse
public void onResponse(Call<Example> call,Response<Example> response) {
try {
current_temp.setText(response.body().getMain().getTemp() + " ℃");
current_output.setText(response.body().getWeather().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() + " %");
} catch (Exception e) {
Log.e("TAG","No City found");
Toast.makeText(getActivity(),Toast.LENGTH_SHORT).show();
}
}
- 空检查
更新您的活动 onResponse
,如下所示。
public void onResponse(Call<Example> call,Response<Example> response) {
if (response.isSuccessful() && response.body() != null) {
time_field.setText("Last Updated:" + " " + response.body().getDt());
} else {
time_field.setText("Last Updated: Unknown");
Log.e("TAG",Toast.LENGTH_SHORT).show();
}
}
像下面那样更新您的片段 onResponse
public void onResponse(Call<Example> call,Response<Example> response) {
if (response.isSuccessful() && response.body() != null) {
current_temp.setText(response.body().getMain().getTemp() + " ℃");
current_output.setText(response.body().getWeather().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() + " %");
} else {
Log.e("TAG",Toast.LENGTH_SHORT).show();
}
}
注意:有一点空间可以改进您的代码并设计得更好,例如避免在搜索点击时对 API 的额外调用,一个来自 Activity,另一个来自片段。但是所有这些建议都超出了这个问题的范围,所以我会坚持使用 I just need the best method to handle the exceptions
的 OP 请求。
您可以在捕获异常时使用 try catch 块,您可以吐司消息城市未找到,这样您的应用就不会崩溃。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。