如何阻止异常搜索不可用/无城市? [英] How to stop exception from searching Unavailable/no cities?

查看:40
本文介绍了如何阻止异常搜索不可用/无城市?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个天气应用程序,可以搜索在 EditText 上输入的任何城市,它运行良好.但问题是,每当我搜索不可用的城市或将 EditText 留空时,应用程序就会崩溃并报告 (我的应用程序)已停止" 在我的手机上单击搜索按钮(仅在我搜索不可用城市/未搜索城市时才会发生),它可以正确搜索任何有效城市.

I have a Weather app that searches for any city typed on the EditText and it works very well. But the problem is that the app crashes and reports "(my app) has stopped" on my phone whenever I search for an unavailable city or I leave the EditText empty and click the search button(this only happens when I search an unavailable city/no city is searched), It can search any valid city correctly.

这是我的 Logcat 显示的内容(仅在搜索不可用城市时):

Here's what my Logcat displays(only when an unavailable city is searched):

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 为空).

when no city is searched(EditText is empty).

因此,我试图停止对此负责的异常,并编写一个祝酒词/消息告诉用户no city found";当搜索不可用/没有城市时.请问我该怎么做?到目前为止,我已经尝试添加:

So I'm trying to stop the exception responsible for that and as well write a toast/message to tell the user "no city found" when an unavailable/no city is searched. Please how do I do that? So far, I've tried adding:

Log.d(TAG, "No City found"); 

在我的

@Override
                    public void onFailure(@NotNull Call<Example> call, @NotNull Throwable t) {
                        t.printStackTrace();
                    }

HomeActivity 中的方法,但它仍然崩溃.

the method in HomeActivity, but it still crashes.

这是我的具体代码:

HomeActivity.java:

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:

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

}

推荐答案

正如 OP 所说我只需要最好的方法来处理异常

让我举两个例子来说明您的情况,以避免崩溃并为 Activity 和 Fragment 显示 Toast.

Let me give two examples for your case to avoid the crash and show toast for both Activity and Fragment.

  • 尝试/捕捉

更新您的活动 onResponse,如下所示.

Update your Activity onResponse like below.

                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

Update your Fragment `onResponse like below

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(), "No City found", Toast.LENGTH_SHORT).show();
            }

        }

  • 空检查
  • 更新您的活动 onResponse,如下所示.

    Update your Activity onResponse like below.

                        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", "No City found");
                            Toast.makeText(HomeActivity.this, "No City found", Toast.LENGTH_SHORT).show();
                        }
    
                    }
    

    像下面这样更新你的片段 onResponse

    Update your Fragment onResponse like below

    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", "No City found");
                    Toast.makeText(getActivity(), "No City found", Toast.LENGTH_SHORT).show();
                }
    
    
            }
    

    注意:有一些改进代码和设计更好的空间,比如避免在搜索点击时额外调用 API,一个来自 Activity,另一个来自片段.但是所有这些建议都超出了这个问题的范围,所以我将坚持 OP 请求,即 我只需要处理异常的最佳方法.

    Note: There is a bit of scope to improve your code and design a better, like to avoid an extra call to API on search click, one from Activity and another in the fragment. But all those suggestion will be out of the scope of this question, So I will stick to OP request which is I just need the best method to handle the exceptions.

    这篇关于如何阻止异常搜索不可用/无城市?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆