1

I'm new to Retrofit, I have an activity hosting 3 fragments for a weather app. My FirstFragment is where the current weather data will be displayed using OpenWeatherMap One call API https://openweathermap.org/api/one-call-api. I noticed that retrofit request calls cannot be made on the fragment class, so I tried using my Activity class and everything worked properly except these following lines:

call.enqueue(new Callback<WeatherResponse>() {
        @Override
        public void onResponse(@NonNull Call < WeatherResponse > call, @NonNull Response < WeatherResponse > response) {
            if (response.code() == 200) {
                WeatherResponse weatherResponse = response.body();
                assert weatherResponse != null;

            time_zone.setText(response.body().getTimezone());
            time_field.setText(response.body().getCurrent.getDt());
            current_temp.setText(response.body().getCurrent().getTemp()+" ℃");
            current_output.setText(response.body().getCurrent().getWeather().getDescription);
            rise_time.setText(response.body().getCurrent().getSunrise()+" AM");
            set_time.setText(response.body().getCurrent().getSunset()+" PM");
            temp_out.setText(response.body().getCurrent().getTemp()+" ℃");
            Press_out.setText(response.body().getCurrent().getPressure()+" hpa");
            Humid_out.setText(response.body().getCurrent().getHumidity()+" %");
            Ws_out.setText(response.body().getCurrent).getWind_speed()+" Km/h");
            Visi_out.setText(response.body().getCurrent().getVisibility()+" m");
            UV_out.setText(response.body().getCurrent().getUvi()); 

showing error Cannot resolve Symbol "response". What can be done to fix it, please? My full code: HomeActivity.java

public class HomeActivity extends AppCompatActivity {
    public static String BaseUrl = "http://api.openweathermap.org/";
    public static String AppId = "";
    public static String lat = "9.0574";
    public static String lon = "7.4898";
    // User Timezone name, current time, current temperature, current condition, sunrise, sunset, temperature, pressure, humidity, wind_speed, visibility, UV Index
    TextView time_zone, time_field, current_temp, current_output, rise_time, set_time, temp_out, Press_out, Humid_out, Ws_out, Visi_out, UV_out;
    ConstraintLayout constraintLayout;
    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_zone = findViewById(R.id.textView9);
        time_field = findViewById(R.id.textView4);
        current_temp = findViewById(R.id.textView10);
        current_output = findViewById(R.id.textView11);
        rise_time = findViewById(R.id.textView25);
        set_time = findViewById(R.id.textView26);
        temp_out = findViewById(R.id.textView28);
        Press_out = findViewById(R.id.textView29);
        Humid_out = findViewById(R.id.textView30);
        Ws_out = findViewById(R.id.textView33);
        Visi_out = findViewById(R.id.textView34);
        UV_out = findViewById(R.id.textView35);

        BottomNavigationView bottomNavigationView = findViewById(R.id.bottomNavigationView);
        NavController navController = Navigation.findNavController(this, R.id.fragment);
        NavigationUI.setupWithNavController(bottomNavigationView, navController);

        constraintLayout = findViewById(R.id.layout);
        constraintLayout.setBackgroundResource(R.drawable.dubai);
        _t = new Timer();
        _t.scheduleAtFixedRate(new TimerTask() {
            @Override
            public void run() {
                runOnUiThread(new Runnable() { // run on ui thread
                    @Override
                    public void run() {
                        if (count < drawable.length) {

                            constraintLayout.setBackgroundResource(drawable[count]);
                            count = (count + 1) % drawable.length;
                        }
                    }
                });
            }
        }, 5000, 5000);
    }
    Retrofit retrofit = new Retrofit.Builder()
            .baseUrl(BaseUrl)
            .addConverterFactory(GsonConverterFactory.create())
            .build();
    WeatherService service = retrofit.create(WeatherService.class);
    Call<WeatherResponse> call = service.getCurrentWeatherData(lat, lon, AppId);
        call.enqueue(new Callback<WeatherResponse>() {
        @Override
        public void onResponse(@NonNull Call < WeatherResponse > call, @NonNull Response < WeatherResponse > response) {
            if (response.code() == 200) {
                WeatherResponse weatherResponse = response.body();
                assert weatherResponse != null;

                time_zone.setText(response.body().getTimezone());
                time_field.setText(response.body().getCurrent.getDt());
                current_temp.setText(response.body().getCurrent().getTemp()+" ℃");
                current_output.setText(response.body().getCurrent().getWeather().getDescription);
                rise_time.setText(response.body().getCurrent().getSunrise()+" AM");
                set_time.setText(response.body().getCurrent().getSunset()+" PM");
                temp_out.setText(response.body().getCurrent().getTemp()+" ℃");
                Press_out.setText(response.body().getCurrent().getPressure()+" hpa");
                Humid_out.setText(response.body().getCurrent().getHumidity()+" %");
                Ws_out.setText(response.body().getCurrent).getWind_speed()+" Km/h");
                Visi_out.setText(response.body().getCurrent().getVisibility()+" m");
                UV_out.setText(response.body().getCurrent().getUvi());

            }
        }
    }
}

WeatherService.java

public interface WeatherService {
    @GET("data/2.5/weather?")
    Call<WeatherResponse> getCurrentWeatherData(@Query("lat") String lat, @Query("lon") String lon, @Query("APPID") String app_id);
}

JSON Response:

{
   "lat":9.08,
   "lon":7.4,
   "timezone":"Africa/Lagos",
   "timezone_offset":3600,
   "current":{
      "dt":1609157237,
      "sunrise":1609134244,
      "sunset":1609175993,
      "temp":305.15,
      "feels_like":304.63,
      "pressure":1012,
      "humidity":29,
      "dew_point":284.9,
      "uvi":8.32,
      "clouds":82,
      "visibility":5000,
      "wind_speed":1.5,
      "wind_deg":200,
      "weather":[
         {
            "id":721,
            "main":"Haze",
            "description":"haze",
            "icon":"50d"
         }
      ]
   }

I converted my JSON to GSON using http://www.jsonschema2pojo.org/

Current.java:

public class Current {
    @SerializedName("dt")
    @Expose
    private Integer dt;
    @SerializedName("sunrise")
    @Expose
    private Integer sunrise;
    @SerializedName("sunset")
    @Expose
    private Integer sunset;
    @SerializedName("temp")
    @Expose
    private Double temp;
    @SerializedName("feels_like")
    @Expose
    private Double feelsLike;
    @SerializedName("pressure")
    @Expose
    private Integer pressure;
    @SerializedName("humidity")
    @Expose
    private Integer humidity;
    @SerializedName("dew_point")
    @Expose
    private Double dewPoint;
    @SerializedName("uvi")
    @Expose
    private Double uvi;
    @SerializedName("clouds")
    @Expose
    private Integer clouds;
    @SerializedName("visibility")
    @Expose
    private Integer visibility;
    @SerializedName("wind_speed")
    @Expose
    private Double windSpeed;
    @SerializedName("wind_deg")
    @Expose
    private Integer windDeg;
    @SerializedName("weather")
    @Expose
    private List<Weather> weather = null;

    public Integer getDt() {
        return dt;
    }

    public void setDt(Integer dt) {
        this.dt = dt;
    }

    public Integer getSunrise() {
        return sunrise;
    }

    public void setSunrise(Integer sunrise) {
        this.sunrise = sunrise;
    }

    public Integer getSunset() {
        return sunset;
    }

    public void setSunset(Integer sunset) {
        this.sunset = sunset;
    }

    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 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 Double getDewPoint() {
        return dewPoint;
    }

    public void setDewPoint(Double dewPoint) {
        this.dewPoint = dewPoint;
    }

    public Double getUvi() {
        return uvi;
    }

    public void setUvi(Double uvi) {
        this.uvi = uvi;
    }

    public Integer getClouds() {
        return clouds;
    }

    public void setClouds(Integer clouds) {
        this.clouds = clouds;
    }

    public Integer getVisibility() {
        return visibility;
    }

    public void setVisibility(Integer visibility) {
        this.visibility = visibility;
    }

    public Double getWindSpeed() {
        return windSpeed;
    }

    public void setWindSpeed(Double windSpeed) {
        this.windSpeed = windSpeed;
    }

    public Integer getWindDeg() {
        return windDeg;
    }

    public void setWindDeg(Integer windDeg) {
        this.windDeg = windDeg;
    }

    public List<Weather> getWeather() {
        return weather;
    }

    public void setWeather(List<Weather> weather) {
        this.weather = weather;
    }
}

Weather.java:

public class Weather {
@SerializedName("id")
@Expose
private Integer id;
@SerializedName("main")
@Expose
private String main;
@SerializedName("description")
@Expose
private String description;
@SerializedName("icon")
    @Expose
    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;
    }
}

WeatherResponse.java:

public class WeatherResponse {
@SerializedName("lat")
@Expose
private Double lat;
@SerializedName("lon")
@Expose
private Double lon;
@SerializedName("timezone")
@Expose
private String timezone;
@SerializedName("timezone_offset")
@Expose
private Integer timezoneOffset;
@SerializedName("current")
    @Expose
    private Current current;

    public Double getLat() {
        return lat;
    }

    public void setLat(Double lat) {
        this.lat = lat;
    }

    public Double getLon() {
        return lon;
    }

    public void setLon(Double lon) {
        this.lon = lon;
    }

    public String getTimezone() {
        return timezone;
    }

    public void setTimezone(String timezone) {
        this.timezone = timezone;
    }

    public Integer getTimezoneOffset() {
        return timezoneOffset;
    }

    public void setTimezoneOffset(Integer timezoneOffset) {
        this.timezoneOffset = timezoneOffset;
    }

    public Current getCurrent() {
        return current;
    }

    public void setCurrent(Current current) {
        this.current = current;
    }

}

I also want to make my fragment class make use of the Activity data, how to do that, please?

Chinez
  • 551
  • 2
  • 6
  • 29
  • remove all spaces from `Response < WeatherResponse >` and `Call < WeatherResponse >` – Priyanka Jan 05 '21 at 04:31
  • @Priyankagb it still didn't dix – Chinez Jan 05 '21 at 11:09
  • `Response response` are you getting compile-time error or run time error here? – Priyanka Jan 05 '21 at 12:02
  • @Priyanka I have neither ran nor compiled it, but I'm getting responses from 3 classes and only weatherResponse is included in the call, I think that's the issue and I want to include the other 2 classes I posted up properly(current & Weather). Please check the post again, I converted my JSON to GSON using http://www.jsonschema2pojo.org/ – Chinez Jan 05 '21 at 12:05
  • can you check the response class you have imported is correct or not? – PJain Jan 11 '21 at 12:13
  • My intuition tells me that you probably forgot to open/close some braces or parentheses... `{ } ( )` – JensV Jan 11 '21 at 13:00

3 Answers3

2

This piece of code is outside of onCreate

    Retrofit retrofit = new Retrofit.Builder()
        .baseUrl(BaseUrl)
        .addConverterFactory(GsonConverterFactory.create())
        .build();
    WeatherService service = retrofit.create(WeatherService.class);
    Call < WeatherResponse > call = service.getCurrentWeatherData(lat, lon, AppId);
    // .... etc.

It needs to be inside a method; onCreate for example.

You can only have declarations and default assignments in the class body. Any other code must be within a method body.

You probably closed the brace of onCreate to early accidentally.


Note: This also explains why you get so many errors. You just have so many lines of code which are, to the compiler, totally out of place and thus marks everything as incorrect.

JensV
  • 3,997
  • 2
  • 19
  • 43
  • I don't think your right about the oncreate, a tutorial I learned from wrapped theirs outside the bracket https://www.c-sharpcorner.com/article/how-to-create-weather-app-using-retrofit-2-in-android/ but I appreciate your effort to help me – Chinez Jan 11 '21 at 13:46
  • @Chinez From your tutorial, they put it inside `void getCurrentData() { .... }` which you are not doing – JensV Jan 11 '21 at 13:47
  • Furthermore, `onCreate` was only an example. As stated it needs to be inside a method. Whether that's `onCreate` or `getCurrentData` depends on what you're trying to do – JensV Jan 11 '21 at 13:50
  • Yeah, I tried to avoid getCurrentData because he wrapped it in a button onclicklistener which I don't want to use. I don't want to click the button before the data is displayed – Chinez Jan 11 '21 at 13:54
  • well then either call getCurrentData directly from onCreate or put the code in onCreate – JensV Jan 11 '21 at 13:54
  • Calling getCurrentData didn't work, then putting code in oncreate worked thanks, then i get 1 error in this line NavController navController = Navigation.findNavController(this, R.id.fragment); saying: Required type: Activity, provided: Callback – Chinez Jan 11 '21 at 14:15
  • 1
    @Chinez that doesn't make sense from the current provided state of the code. From the error I'm assuming this is inside the callback where you'd simply pass `HomeActivity.this` instead of `this`. Anyhow, this goes out of scope of the current question. If my answer fixed the stated problem, accept it and for any further problems, post a new question – JensV Jan 11 '21 at 14:21
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/227159/discussion-between-chinez-and-jensv). – Chinez Jan 11 '21 at 14:25
0

It might be rather something alike this:

@Override
public void onResponse(@NonNull Call<WeatherResponse> call, @NonNull Response <WeatherResponse> response) {
    if (response.code() == 200) {
        WeatherResponse weatherResponse = response.body();
        time_zone.setText(weatherResponse.getTimezone());
        time_field.setText(weatherResponse.getCurrent.getDt());
        current_temp.setText(weatherResponse.getCurrent().getTemp()+" ℃");
        rise_time.setText(weatherResponse.getCurrent().getSunrise()+" AM");
        set_time.setText(weatherResponse.getCurrent().getSunset()+" PM");
        temp_out.setText(weatherResponse.getCurrent().getTemp()+" ℃");
        Press_out.setText(weatherResponse.getCurrent().getPressure()+" hpa");
        Humid_out.setText(weatherResponse.getCurrent().getHumidity()+" %");
        Ws_out.setText(weatherResponse.getCurrent).getWind_speed()+" Km/h");
        Visi_out.setText(weatherResponse.getCurrent().getVisibility()+" m");
        UV_out.setText(weatherResponse.getCurrent().getUvi()); 
    }
}

Make sure to have class WeatherResponse and Current properly annotated.

That ? in the URL is useless.

Martin Zeitler
  • 1
  • 19
  • 155
  • 216
  • Please check my classes up now. I've properly formatted and annotated the classes using http://www.jsonschema2pojo.org/ – Chinez Jan 05 '21 at 11:59
0

make sure your enqueue() looks like this

call.enqueue(new Callback<WeatherResponse>() {
            @Override
            public void onResponse(@NotNull Call<WeatherResponse> call, @NotNull Response<WeatherResponse> response) {
                if (response.body() != null) {
                     //...
                }
            }

            @Override
            public void onFailure(@NotNull Call<WeatherResponse> call, @NotNull Throwable t) {
                t.printStackTrace();
            }
        });
Priyanka
  • 3,369
  • 1
  • 10
  • 33
  • Thanks but your including only a class (WeatherResponse), I need to include current & weather in the call – Chinez Jan 05 '21 at 12:12
  • you can get Current & weather from the WeatherResponse using weatherResponse.getCurrent() & weatherResponse.getCurrent().getWeather().get(0) – Priyanka Jan 05 '21 at 12:17
  • in the call you can do only like this answer – Priyanka Jan 05 '21 at 12:17
  • So you mean I don't have to include current & weather in the "call.enqueue(new Callback()" despite current & weather is a different class? – Chinez Jan 05 '21 at 12:23
  • i'm not getting you – Priyanka Jan 05 '21 at 12:24
  • What I'm saying is that WeatherResponse, Current & Weather are all different classes when I used http://www.jsonschema2pojo.org/ to convert them to GSON, but your suggesting I should only include WeatherResponse in the call.enqueue(new Callback<> is it right like that? – Chinez Jan 05 '21 at 12:28
  • yes, after getting the response you will able to access those classes from `weatherResponse` – Priyanka Jan 05 '21 at 12:30
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/226869/discussion-between-chinez-and-priyanka). – Chinez Jan 05 '21 at 12:46