Thursday, 15 July 2021

Having problem trying to display my app's weather icons

I'm done with almost every other setup for my app, and I've been trying for days to figure out how I can display weather icons for my app according to its city's response but I still have no idea how to do that. To my surprise, I haven't seen anyone with the same issue. I've checked this site, searched several sites for tutorials on it, checked youtube, visited code Project for help https://www.codeproject.com/Questions/5307462/How-to-setup-my-app-weather-icons, asked on quora and discord and Checked different weather open sources on Github but I found no place where they tried to achieve a similar thing. So I eventually decided to come here for help. And I will surely appreciate it if anyone can help.

Following the API instructions, I'm using https://openweathermap.org/weather-conditions. There are 9 main weather conditions. This is my goal while using it:

  • When the app is open at first, display no icon.
  • If a user searches for a city and the response he gets is a clear sky, display the Clear Sky icon;
  • Otherwise, if the response is Few Clouds in that city, display the Few Clouds icon
  • Otherwise, if the response is Scattered clouds in that city, display the Scattered clouds icon
  • Otherwise, if the response is Broken Clouds in that city, display the Broken Clouds icon
  • Otherwise, if the response is Shower rain in that city, display the Shower rain icon
  • Otherwise, if the response is Rain in that city, display the Rain icon
  • Otherwise, if the response is Thunderstorm in that city, display the Thunderstorm icon
  • Otherwise, if the response is Snow in that city, display the Snow icon
  • Otherwise, if the response is Mist there, display the Mist icon.

OpenWeatherMap https://openweathermap.org/current only made provisions for setting up the weather icons if you're using their own icons i.e weather.icon. But I only want to make use of the Icons I have in my Drawable. I have all the 9 icons I want to use in my drawable.

I feel I may need to create a method, along with if-else and maybe a case statement, but still, I don't know the way to do that in a way it will rightly work with the app. I lack experience with that specifically.

I don't have a specific response on the app, as it can search for any city, but an example of the response it gets is like this:

...
   "weather":[
      {
         "id":801,
         "main":"Clouds",
         "description":"few clouds",
         "icon":"02n"
      }
   ],
   ...

Here is my code:

FirstFragment.java:

public class FirstFragment extends Fragment {

    private WeatherDataViewModel viewModel;

    public FirstFragment() {
        // Required empty public constructor
    }

    @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
        final TextView current_temp = rootView.findViewById(R.id.textView10);
        final TextView current_output = rootView.findViewById(R.id.textView11);
        final TextView rise_time = rootView.findViewById(R.id.textView25);
        final TextView set_time = rootView.findViewById(R.id.textView26);
        final TextView temp_out = rootView.findViewById(R.id.textView28);
        final TextView Press_out = rootView.findViewById(R.id.textView29);
        final TextView Humid_out = rootView.findViewById(R.id.textView30);
        final TextView Ws_out = rootView.findViewById(R.id.textView33);
        final TextView Visi_out = rootView.findViewById(R.id.textView34);
        final TextView Cloud_out = rootView.findViewById(R.id.textView35);

        // Get our ViewModel instance
        viewModel = new ViewModelProvider(this).get(WeatherDataViewModel.class);

        // And whenever the data changes, refresh the UI
        viewModel.getWeatherDataLiveData().observe(getViewLifecycleOwner(), data -> {
            if (data != null) {
                current_temp.setVisibility(View.VISIBLE);
                current_temp.setText(data.getMain().getTemp() + " ℃");
                current_output.setVisibility(View.VISIBLE);
                current_output.setText(data.getWeather().get(0).getDescription());
                rise_time.setVisibility(View.VISIBLE);
                rise_time.setText(data.getSys().getSunrise() + " ");
                set_time.setVisibility(View.VISIBLE);
                set_time.setText(data.getSys().getSunset() + " ");
                temp_out.setVisibility(View.VISIBLE);
                temp_out.setText(data.getMain().getTemp() + " ℃");
                Press_out.setVisibility(View.VISIBLE);
                Press_out.setText(data.getMain().getPressure() + " hpa");
                Humid_out.setVisibility(View.VISIBLE);
                Humid_out.setText(data.getMain().getHumidity() + " %");
                Ws_out.setVisibility(View.VISIBLE);
                Ws_out.setText(data.getWind().getSpeed() + " Km/h");
                Visi_out.setVisibility(View.VISIBLE);
                Visi_out.setText(data.getVisibility() + " m");
                Cloud_out.setVisibility(View.VISIBLE);
                Cloud_out.setText(data.getClouds().getAll() + " %");
            } else {
                Log.e("TAG", "No City found");
                current_temp.setVisibility(View.GONE);
                current_output.setVisibility(View.GONE);
                rise_time.setVisibility(View.GONE);
                set_time.setVisibility(View.GONE);
                temp_out.setVisibility(View.GONE);
                Press_out.setVisibility(View.GONE);
                Humid_out.setVisibility(View.GONE);
                Ws_out.setVisibility(View.GONE);
                Visi_out.setVisibility(View.GONE);
                Cloud_out.setVisibility(View.GONE);
                Toast.makeText(requireActivity(), "No City found", Toast.LENGTH_SHORT).show();
            }
        });

        return rootView;
    }

    public void getWeatherData(String name) {
        // The ViewModel controls loading the data, so we just
        // tell it what the new name is - this kicks off loading
        // the data, which will automatically call through to
        // our observe() call when the data load completes
        viewModel.setCityName(name);
    }
}

For my ViewModel:

WeatherDataViewModel:

public class WeatherDataViewModel extends ViewModel {
    // This will save the city name
    private SavedStateHandle state;

    // This is where we'll store our result from the server
    private MutableLiveData<Example> mutableWeatherData = new MutableLiveData<>();

    public WeatherDataViewModel(SavedStateHandle savedStateHandle) {
        state = savedStateHandle;
        String savedCityName = state.get("name");
        if (savedCityName != null) {
            // We already had a previously saved name, so we'll
            // start loading right away
            loadData();
        }
    }

    // This is what our Fragment will use to get the latest weather data
    public LiveData<Example> getWeatherDataLiveData() {
        return mutableWeatherData;
    }

    // When you get a new city name, we'll save that in our
    // state, then load the new data from the server
    public void setCityName(String name) {
        state.set("name", name);
        loadData();
    }

    private void loadData() {
        // Get the last name that was set
        String name = state.get("name");

        // Now kick off a load from the server
        ApiInterface apiInterface = ApiClient.getClient().create(ApiInterface.class);

        Call<Example> call = apiInterface.getWeatherData(name);

        call.enqueue(new Callback<Example>() {
            @Override
            public void onResponse(@NonNull Call<Example> call, @NonNull Response<Example> response) {
                // Save the response we've gotten
                // This will automatically update our UI
                mutableWeatherData.setValue(response.body());
            }

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


from Having problem trying to display my app's weather icons

No comments:

Post a Comment