Добавить в корзинуПозвонить
Найти в Дзене

Создание мобильного приложения для прогноза погоды на Android с использованием Java и Retrofit

В этой статье мы рассмотрим, как создать простое мобильное приложение для отображения прогноза погоды с использованием Android Studio на языке Java. Мы будем использовать API Яндекс.Погоды для получения актуальных данных о погоде. Синхронизируйте проект. Создайте класс для получения данных о погоде. В вашем проекте создайте новый пакет, например, models и добавьте следующие классы: Создайте пакет api, где будет находиться интерфейс для работы с API Яндекс.Погоды. Создайте класс RetrofiteInstans для инициализации Retrofit. Создайте класс ForecastAdapter для отображения данных о прогнозе в RecyclerView. Теперь соберите все вместе в MainActivity, чтобы получать данные о погоде и отображать их. Создайте пользовательский интерфейс с помощью XML файлов. Начнем с activity_main.xml. Создайте XML файл для элементов списка прогноза item_forecast.xml. Теперь вы можете запустить приложение и увидеть текущую погоду и прогноз для города Пермь. Используя Retrofit, мы смогли легко интегр
Оглавление

В этой статье мы рассмотрим, как создать простое мобильное приложение для отображения прогноза погоды с использованием Android Studio на языке Java. Мы будем использовать API Яндекс.Погоды для получения актуальных данных о погоде.

Шаг 1: Настройка проекта

  1. Создайте новый проект в Android Studio:Выберите Empty Activity.
    Введите имя проекта, например
    WeatherApp.
    Убедитесь, что язык установлен на
    Java, а минимальная версия API соответствует вашим требованиям (рекомендуется API 21 и выше).
  2. Добавьте разрешение на доступ в интернет в файл AndroidManifest.xml:
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.INTERNET"/>

  1. Добавьте зависимости на Retrofit и Gson в файл build.gradle (Module: app):
implementation("com.squareup.retrofit2:retrofit:2.9.0") implementation("com.squareup.retrofit2:converter-gson:2.9.0")
implementation("com.squareup.okhttp3:logging-interceptor:5.0.0-alpha.2")
implementation("com.squareup.retrofit2:retrofit:2.9.0") implementation("com.squareup.retrofit2:converter-gson:2.9.0") implementation("com.squareup.okhttp3:logging-interceptor:5.0.0-alpha.2")

Синхронизируйте проект.

Шаг 2: Создание моделей данных

Создайте класс для получения данных о погоде. В вашем проекте создайте новый пакет, например, models и добавьте следующие классы:

WeatherResponse.java

import com.google.gson.annotations.SerializedName; import java.util.ArrayList;
import java.util.List;
public class WeatherResponse {
@SerializedName("fact")
private Fact fact;
@SerializedName("forecasts")
private List<Forecasts> forecasts = new ArrayList<>();
public List<Forecasts> getForecasts() {
return forecasts;
}
public Fact getFact() {
return fact;
}
public void setFact(Fact fact) {
this.fact = fact;
}
}
import com.google.gson.annotations.SerializedName; import java.util.ArrayList; import java.util.List; public class WeatherResponse { @SerializedName("fact") private Fact fact; @SerializedName("forecasts") private List<Forecasts> forecasts = new ArrayList<>(); public List<Forecasts> getForecasts() { return forecasts; } public Fact getFact() { return fact; } public void setFact(Fact fact) { this.fact = fact; } }

Fact.java

import com.google.gson.annotations.SerializedName; public class Fact {
@SerializedName("temp")
private int temp;
public int getTemp() {
return temp;
}
public void setTemp(int temp) {
this.temp = temp;
}
}
import com.google.gson.annotations.SerializedName; public class Fact { @SerializedName("temp") private int temp; public int getTemp() { return temp; } public void setTemp(int temp) { this.temp = temp; } }

Forecasts.java

public class Forecasts {
@SerializedName("date")
private String date;
@SerializedName("parts")
private Parts parts;
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
public Parts getParts() {
return parts;
}
public void setParts(Parts parts) {
this.parts = parts;
}
}
public class Forecasts { @SerializedName("date") private String date; @SerializedName("parts") private Parts parts; public String getDate() { return date; } public void setDate(String date) { this.date = date; } public Parts getParts() { return parts; } public void setParts(Parts parts) { this.parts = parts; } }

Parts.java

public class Parts { @SerializedName("day")
private Day day;
public Day getDay() {
return day;
}
public void setDay(Day day) {
this.day = day;
}
}
public class Parts { @SerializedName("day") private Day day; public Day getDay() { return day; } public void setDay(Day day) { this.day = day; } }

Day.java

public class Day { @SerializedName("temp_max")
private int temp_max;
@SerializedName("temp_min")
private int temp_min;
@SerializedName("condition")
private String condition;
public int getTemp_max() {
return temp_max;
}
public void setTemp_max(int temp_max) {
this.temp_max = temp_max;
}
public String getCondition() {
return condition;
}
public void setCondition(String condition) {
this.condition = condition;
}
public int getTemp_min() {
return temp_min;
}
public void setTemp_min(int temp_min) {
this.temp_min = temp_min;
}
}
public class Day { @SerializedName("temp_max") private int temp_max; @SerializedName("temp_min") private int temp_min; @SerializedName("condition") private String condition; public int getTemp_max() { return temp_max; } public void setTemp_max(int temp_max) { this.temp_max = temp_max; } public String getCondition() { return condition; } public void setCondition(String condition) { this.condition = condition; } public int getTemp_min() { return temp_min; } public void setTemp_min(int temp_min) { this.temp_min = temp_min; } }

Шаг 3: Создание интерфейса API

Создайте пакет api, где будет находиться интерфейс для работы с API Яндекс.Погоды.

WeatherApi.java

import retrofit2.Call; import retrofit2.http.GET;
import retrofit2.http.Headers;
import retrofit2.http.Query;
public interface WeatherApi {
@GET("v2/forecast")
@Headers("X-Yandex-API-Key: demo_yandex_weather_api_key_ca6d09349ba0")
Call<WeatherResponse> getWeather(
@Query("lat") double lat,
@Query("lon") double lon,
@Query("lang") String lang,
@Query("limit") int limit,
@Query("hours") boolean hours,
@Query("extra") boolean extra
);
}
import retrofit2.Call; import retrofit2.http.GET; import retrofit2.http.Headers; import retrofit2.http.Query; public interface WeatherApi { @GET("v2/forecast") @Headers("X-Yandex-API-Key: demo_yandex_weather_api_key_ca6d09349ba0") Call<WeatherResponse> getWeather( @Query("lat") double lat, @Query("lon") double lon, @Query("lang") String lang, @Query("limit") int limit, @Query("hours") boolean hours, @Query("extra") boolean extra ); }

Шаг 4: Создание Retrofit Instance

Создайте класс RetrofiteInstans для инициализации Retrofit.

RetrofiteInstans.java

import retrofit2.Retrofit; import retrofit2.converter.gson.GsonConverterFactory;
public class RetrofiteInstans {
private static final String BASE_URL = "https://api.weather.yandex.ru/";
public static final WeatherApi api;
static {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.build();
api = retrofit.create(WeatherApi.class);
}
}
import retrofit2.Retrofit; import retrofit2.converter.gson.GsonConverterFactory; public class RetrofiteInstans { private static final String BASE_URL = "https://api.weather.yandex.ru/"; public static final WeatherApi api; static { Retrofit retrofit = new Retrofit.Builder() .baseUrl(BASE_URL) .addConverterFactory(GsonConverterFactory.create()) .build(); api = retrofit.create(WeatherApi.class); } }

Шаг 5: Создание адаптера для RecyclerView

Создайте класс ForecastAdapter для отображения данных о прогнозе в RecyclerView.

ForecastAdapter.java

import android.view.LayoutInflater; import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import java.util.List;
public class ForecastAdapter extends RecyclerView.Adapter<ForecastAdapter.ForecastViewHolder> {
private List<Forecasts> forecasts;
public ForecastAdapter(List<Forecasts> forecasts) {
this.forecasts = forecasts;
}
@NonNull
@Override
public ForecastAdapter.ForecastViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_forecast, parent, false);
return new ForecastViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull ForecastAdapter.ForecastViewHolder holder, int position) {
Forecasts forecast = forecasts.get(position);
String day = forecast.getDate();
holder.dayTextView.setText(day);
String temp = forecast.getParts().getDay().getTemp_max() + "°/" + forecast.getParts().getDay().getTemp_min() + "°";
holder.temperatureTextView.setText(temp);
}
@Override
public int getItemCount() {
return forecasts.size();
}
class ForecastViewHolder extends RecyclerView.ViewHolder {
TextView dayTextView;
TextView temperatureTextView;
public ForecastViewHolder(@NonNull View item) {
super(item);
dayTextView = item.findViewById(R.id.tvDay);
temperatureTextView = item.findViewById(R.id.tvTemp);
}
}
}
import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; import androidx.annotation.NonNull; import androidx.recyclerview.widget.RecyclerView; import java.util.List; public class ForecastAdapter extends RecyclerView.Adapter<ForecastAdapter.ForecastViewHolder> { private List<Forecasts> forecasts; public ForecastAdapter(List<Forecasts> forecasts) { this.forecasts = forecasts; } @NonNull @Override public ForecastAdapter.ForecastViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_forecast, parent, false); return new ForecastViewHolder(view); } @Override public void onBindViewHolder(@NonNull ForecastAdapter.ForecastViewHolder holder, int position) { Forecasts forecast = forecasts.get(position); String day = forecast.getDate(); holder.dayTextView.setText(day); String temp = forecast.getParts().getDay().getTemp_max() + "°/" + forecast.getParts().getDay().getTemp_min() + "°"; holder.temperatureTextView.setText(temp); } @Override public int getItemCount() { return forecasts.size(); } class ForecastViewHolder extends RecyclerView.ViewHolder { TextView dayTextView; TextView temperatureTextView; public ForecastViewHolder(@NonNull View item) { super(item); dayTextView = item.findViewById(R.id.tvDay); temperatureTextView = item.findViewById(R.id.tvTemp); } } }

Шаг 6: Реализация MainActivity

Теперь соберите все вместе в MainActivity, чтобы получать данные о погоде и отображать их.

MainActivity.java

import android.os.Bundle; import android.widget.Button;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
public class MainActivity extends AppCompatActivity {
private TextView tvTemperature;
private RecyclerView rcForecast;
private Button btHourlyForecast;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tvTemperature = findViewById(R.id.tvTemperature);
rcForecast = findViewById(R.id.rcForecast);
btHourlyForecast = findViewById(R.id.btHourlyForecast);
getWeatherData();
}
private void getWeatherData() {
RetrofiteInstans.api.getWeather(
58.0105, 56.2502, "ru_RU", 7, true, false
).enqueue(new Callback<WeatherResponse>() {
@Override
public void onResponse(Call<WeatherResponse> call, Response<WeatherResponse> response) {
if (response.isSuccessful()) {
WeatherResponse weatherResponse = response.body();
if (weatherResponse != null) {
updateUI(weatherResponse);
}
}
}
@Override
public void onFailure(Call<WeatherResponse> call, Throwable t) {
// Обработка ошибки
}
});
}
private void updateUI(WeatherResponse weatherResponse) {
String temp = weatherResponse.getFact().getTemp() + "°";
tvTemperature.setText(temp);
ForecastAdapter forecastAdapter = new ForecastAdapter(weatherResponse.getForecasts());
rcForecast.setLayoutManager(new LinearLayoutManager(this));
rcForecast.setAdapter(forecastAdapter);
}
}
import android.os.Bundle; import android.widget.Button; import android.widget.TextView; import androidx.appcompat.app.AppCompatActivity; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import retrofit2.Call; import retrofit2.Callback; import retrofit2.Response; public class MainActivity extends AppCompatActivity { private TextView tvTemperature; private RecyclerView rcForecast; private Button btHourlyForecast; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); tvTemperature = findViewById(R.id.tvTemperature); rcForecast = findViewById(R.id.rcForecast); btHourlyForecast = findViewById(R.id.btHourlyForecast); getWeatherData(); } private void getWeatherData() { RetrofiteInstans.api.getWeather( 58.0105, 56.2502, "ru_RU", 7, true, false ).enqueue(new Callback<WeatherResponse>() { @Override public void onResponse(Call<WeatherResponse> call, Response<WeatherResponse> response) { if (response.isSuccessful()) { WeatherResponse weatherResponse = response.body(); if (weatherResponse != null) { updateUI(weatherResponse); } } } @Override public void onFailure(Call<WeatherResponse> call, Throwable t) { // Обработка ошибки } }); } private void updateUI(WeatherResponse weatherResponse) { String temp = weatherResponse.getFact().getTemp() + "°"; tvTemperature.setText(temp); ForecastAdapter forecastAdapter = new ForecastAdapter(weatherResponse.getForecasts()); rcForecast.setLayoutManager(new LinearLayoutManager(this)); rcForecast.setAdapter(forecastAdapter); } }

Шаг 7: Создание пользовательского интерфейса

Создайте пользовательский интерфейс с помощью XML файлов. Начнем с activity_main.xml.

activity_main.xml

<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@drawable/img"
android:orientation="vertical">
<TextView
android:id="@+id/tvTemperature"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Температура"
android:textSize="48sp"
android:layout_marginTop="150dp"
android:layout_gravity="center"
android:textColor="@color/white" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Пермь"
android:textSize="24sp"
android:layout_marginTop="10dp"
android:layout_gravity="center"
android:textColor="@color/white" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/rcForecast"
android:layout_width="250dp"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginTop="200dp"
android:nestedScrollingEnabled="false"/>
<Button
android:id="@+id/btHourlyForecast"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Почасовой прогноз"
android:layout_marginTop="10dp"
android:layout_gravity="center"/>
</LinearLayout>
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:background="@drawable/img" android:orientation="vertical"> <TextView android:id="@+id/tvTemperature" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Температура" android:textSize="48sp" android:layout_marginTop="150dp" android:layout_gravity="center" android:textColor="@color/white" /> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Пермь" android:textSize="24sp" android:layout_marginTop="10dp" android:layout_gravity="center" android:textColor="@color/white" /> <androidx.recyclerview.widget.RecyclerView android:id="@+id/rcForecast" android:layout_width="250dp" android:layout_height="wrap_content" android:layout_gravity="center" android:layout_marginTop="200dp" android:nestedScrollingEnabled="false"/> <Button android:id="@+id/btHourlyForecast" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Почасовой прогноз" android:layout_marginTop="10dp" android:layout_gravity="center"/> </LinearLayout>

item_forecast.xml

Создайте XML файл для элементов списка прогноза item_forecast.xml.

<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="@+id/tvDay"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"/>
<TextView
android:id="@+id/tvTemp"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="wrap_content"/>
</LinearLayout>
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal"> <TextView android:id="@+id/tvDay" android:layout_width="0dp" android:layout_weight="1" android:layout_height="wrap_content"/> <TextView android:id="@+id/tvTemp" android:layout_width="0dp" android:layout_weight="1" android:layout_height="wrap_content"/> </LinearLayout>

Заключение

Теперь вы можете запустить приложение и увидеть текущую погоду и прогноз для города Пермь. Используя Retrofit, мы смогли легко интегрировать API Яндекс.Погоды и отобразить данные в приложении. Вы можете расширить функциональность приложения, добавив дополнительные функции, такие как почасовой прогноз или различные темы оформления.

Если у вас есть какие-либо вопросы или вам нужна помощь с приложением, не стесняйтесь спрашивать!