微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何阻止异常搜索不可用/无城市?

如何解决如何阻止异常搜索不可用/无城市?

我有一个天气应用程序,可以搜索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 举报,一经查实,本站将立刻删除。