Статьи

Как разработать приложение Android Weather с помощью Weatherlib

Некоторые пользователи спрашивали меня о том, как использовать Weatherlib . В этом посте хочу описать, как его использовать.

Это Android-библиотека, которая помогает быстро и легко разрабатывать погодные приложения. В этом посте описаны основные концепции, стоящие за библиотекой, чтобы вы могли лучше понять ее.

Если вас не интересует внутренняя структура библиотеки, вы можете перейти к той части, которая описывает, как кодировать клиент погоды:

«Настройка среды разработки» .

икона

Структура Weatherlib

Библиотека построена из трех разных слоев:

  • Модель данных
  • Поставщики погоды
  • Погодный клиент

Первый уровень, модель данных, представляет информацию, полученную от другого поставщика погоды. Он абстрагирует эту информацию, так что независимо от того, какого поставщика погоды вы выберете, у вас всегда будет одинаковая информация, представленная одинаково и с одинаковыми отношениями между ними.

Поставщики погоды являются связующим звеном с поставщиком погоды. К настоящему времени библиотека поддерживает три поставщика погоды:

  1. Openweathermap
  2. Yahoo! Погода
  3. Weatherunderground

Этот уровень реализует логику, необходимую для извлечения информации от поставщика погоды, анализа полученных данных и в конце процесса эти поставщики заполняют модель данных.

Последний уровень — это клиентский уровень. Этот уровень реализует логику для подключения провайдера погоды (т. Е. Через HTTP-соединение), обработки ошибок соединения и т. Д. Как только данные получены, клиент использует провайдер погоды для анализа данных.

Каждый уровень можно легко расширять и настраивать, чтобы вы могли поддерживать других поставщиков погоды или реализовывать различные способы подключения к поставщикам. Позже мы увидим, как это сделать.

Модель данных Weatherlib

Это модель, которая стоит у основания библиотеки, и вы взаимодействуете с ней, когда хотите получить информацию о погоде.

Диаграмма классов Weatherlib [4]

Класс CurrentWeather содержит всю информацию, связанную с текущими данными о погоде. WeatherHourForecast содержит информацию, связанную с почасовыми данными о погоде, а WeatherForecast содержит информацию, связанную с погодой на следующие дни.

Weatherlib провайдер

Этот слой является сердцем библиотеки, потому что он реализует логику для извлечения информации от поставщика погоды. К настоящему времени библиотека поддерживает три разных погодных провайдера. Каждый поставщик описывается тремя различными классами, которые должны реализовывать три интерфейса:

  • IProviderType , определяющий имя класса, которое необходимо создать для создания провайдера.
  • IWeatherProvider — основной интерфейс, который должен реализовывать весь провайдер погоды, и содержит все методы, необходимые для анализа данных.
  • IWeatherCodeProvider — простой интерфейс для перевода кода погоды в общий формат, чтобы условие кода погоды не зависело от поставщика.

Например, если мы посмотрим на поставщика openweathermap, то имеем:

Weatherlib погода провайдер [4]

Все провайдеры создаются WeatherProviderFactory .

Погодный клиент

Это последний уровень, который обрабатывает соединение с удаленным поставщиком погоды и извлекает данные. Вы можете использовать все протоколы, которые вам нравятся, но обычно используется протокол HTTP. Эти классы обрабатывают также ошибки соединения и так далее. Библиотека предоставляет две разные реализации:

  1. Один основан на залповой либе
  2. Один основан на стандартном HttpConnection, предоставляемом Android

Настройте среду разработки

Использовать библиотеку очень просто, потому что библиотека находится в центральном репозитории Maven, поэтому вам не нужно много работать в Android Studio. После того, как вы создали свой проект, вы должны добавить новую зависимость в проект build.gradle

1
2
3
4
5
dependencies {
    compile 'com.android.support:appcompat-v7:19.+'
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.survivingwithandroid:WeatherLib:1.3.0'
}

Как разработать приложение Weather с помощью Weatherlib

Теперь вы знаете основные слои библиотеки — самое время начать использовать библиотеку. Конечно, когда вы разрабатываете, вам не нужно беспокоиться о внутренних деталях, объясненных к настоящему времени, но вы будете использовать только несколько вещей. Первое, что вам нужно сделать, это получить экземпляр WeatherClient чтобы вы могли использовать его в своем приложении. Этот класс одноэлементный, поэтому его нужно инициализировать только один раз:

1
WeatherClient client = WeatherClientDefault.getInstance();

в этом случае мы хотим использовать клиент по умолчанию на основе библиотеки Volley, в противном случае вы можете использовать StandardHttpClient. Теперь у нас есть наш клиент, мы должны инициализировать его, передавая Контекст :

1
client.init(ctx);

Теперь мы должны настроить нашего клиента, передав ему конфигурацию погоды:

1
2
3
4
5
WeatherConfig config = new WeatherConfig();
config.unitSystem = WeatherConfig.UNIT_SYSTEM.M;
config.lang = "en"; // If you want to use english
config.maxResult = 5; // Max number of cities retrieved
config.numDays = 6; // Max num of days in the forecast

а потом:

1
client.updateWeatherConfig(config);

Теперь клиент настроен, последний шаг — выбрать провайдера, которого мы хотим использовать:

01
02
03
04
05
06
07
08
09
10
IWeatherProvider provider = null;
try {
    //provider = WeatherProviderFactory.createProvider(new YahooProviderType(), config);
    provider = WeatherProviderFactory.createProvider(new OpenweathermapProviderType(), config);
    //provider = WeatherProviderFactory.createProvider(new WeatherUndergroundProviderType(), config);
    client.setProvider(provider);
}
catch (Throwable t) {   
    // There's a problem
}

Окей, сделано! Наш клиент готов к использованию и готов к получению информации.

Поиск идентификатора города

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

  1. Поиск по имени или части имени
  2. Поиск по географическим координатам

В первом случае вы можете использовать:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
private void search(String pattern) {
    client.searchCity(pattern, new WeatherClient.CityEventListener() {
        @Override
        public void onCityListRetrieved(List<City> cityList) {
           // When the data is ready you can implement your logic here
        }
 
        @Override
        public void onWeatherError(WeatherLibException t) {
           // Error
        }
 
        @Override
        public void onConnectionError(Throwable t) {
           // Connection error
        }
    });
}

где pattern — это частичное название города, которое вы ищете. В onCityListRetrived вас есть список городов, который можно передать в ArrayAdapter, например, чтобы показать результат пользователю.

Во втором варианте, используя географические координаты, вы просто имеете:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
client.searchCityByLocation(WeatherClient.createDefaultCriteria(), new WeatherClient.CityEventListener() {
 
     @Override
     public void onCityListRetrieved(List<City> cityList) {
        // Here your logic when the data is available
     }
 
     @Override
     public void onWeatherError(WeatherLibException wle) {
          
     }
 
     @Override
     public void onConnectionError(Throwable t) {
          
     }
 });
}
catch(LocationProviderNotFoundException lpnfe) {
 
}

Обратите внимание, что в строке 1 мы использовали WeatherClient.createDefaultCriteria (), этот метод возвращает некоторые критерии по умолчанию, которые используются для выбора лучшего поставщика местоположения. Если вы хотите использовать свои критерии, вы просто устанавливаете их вручную:

1
2
3
4
Criteria criteria = new Criteria();
criteria.setPowerRequirement(Criteria.POWER_LOW);
criteria.setAccuracy(Criteria.ACCURACY_COARSE);
criteria.setCostAllowed(false);

Текущее состояние погоды

Получив идентификатор города, вы можете запросить у поставщика информацию о текущих погодных условиях:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
client.getCurrentCondition(cityId, new WeatherClient.WeatherEventListener() {
    @Override
    public void onWeatherRetrieved(CurrentWeather weather) {
       // Here we can use the weather information to upadte the view
    }
 
    @Override
    public void onWeatherError(WeatherLibException t) {
         
    }
 
    @Override
    public void onConnectionError(Throwable t) {
         
    }
});

Обратите внимание, что клиент использует интерфейс обратного вызова для уведомления вызывающей стороны о том, что данные готовы. Это происходит, только если вы используете WeatherClientDefault . Используя эти методы обратного вызова, вам не нужно беспокоиться о проблемах ANR, потому что HTTP-запрос происходит в отдельном потоке, и эти запросы не блокируют приложение. Когда данные готовы в строке 3, мы можем использовать их для обновления пользовательского интерфейса, как показано ниже:

1
2
3
4
5
6
7
8
9
@Override
protected void updateView(Object obj) {
    CurrentWeather weather = (CurrentWeather) obj;
    cityText.setText(weather.location.getCity() + "," + weather.location.getCountry());
    condDescr.setText(weather.currentCondition.getCondition() + "(" + weather.currentCondition.getDescr() + ")");
    temp.setText("" + ((int) weather.temperature.getTemp()));
    unitTemp.setText(weather.getUnit().tempUnit);
    ....
}

Прогноз погоды и почасовой прогноз погоды

Если вы хотите, вы можете использовать lib для запроса прогноза и почасовых данных прогноза. Таким же образом, как описано выше, мы имеем:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
client.getForecastWeather(cityId, new WeatherClient.ForecastWeatherEventListener() {
    @Override
    public void onWeatherRetrieved(WeatherForecast forecast) {       
        updateView(forecast);
    }
 
    @Override
    public void onWeatherError(WeatherLibException t) {
 
    }
 
    @Override
    public void onConnectionError(Throwable t) {
        //WeatherDialog.createErrorDialog("Error parsing data. Please try again", MainActivity.this);
    }
});

и для почасового прогноза имеем:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
client.getHourForecastWeather(cityId, new WeatherClient.HourForecastWeatherEventListener() {
    @Override
    public void onWeatherRetrieved(WeatherHourForecast forecast) {
        updateView(foreacst);
    }
 
    @Override
    public void onWeatherError(WeatherLibException wle) {
 
    }
 
    @Override
    public void onConnectionError(Throwable t) {
 
    }
});

Данные кеша

Один аспект, который следует учитывать при разработке приложения погоды, — данные о погоде не изменяются быстро, поэтому рекомендуется кэшировать данные, чтобы вам не приходилось постоянно запрашивать их у удаленного поставщика. Weatherlib пока не предоставляет механизм кэширования, поэтому он должен быть реализован вами, если вы хотите кэшировать полученные результаты. Это можно легко сделать, создав одноэлементный класс, содержащий данные, которые вы извлекаете, например:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
public class AppWeatherClient {
 
    private static AppWeatherClient me;
    private Context ctx;
    private WeatherClient client;
    private WeatherConfig config;
    private WeatherForecast forecast;
 
    private CurrentWeather weather;
 
    private AppWeatherClient() {}
 
    public static AppWeatherClient getInstance() {
        if (me == null)
            me = new AppWeatherClient();
 
        return me;
    }
   
    public CurrentWeather getCurrentWeather() {
        return this.weather;
    }
 
    public void setCurrentWeather(CurrentWeather weather) {
        this.weather = weather;
    }
 
    public WeatherForecast getForecast() {
        return forecast;
    }
 
    public void setForecast(WeatherForecast forecast) {
        this.forecast = forecast;
    }
}

Используя ключ API

Некоторые провайдеры требуют, чтобы вы использовали ключ API (например, Weatherundergroud). Этот ключ API необходим для вызова удаленных методов и получения информации о погоде. Weatherlib предоставляет простой способ обработки таких запросов, и вам не нужно беспокоиться о том, как отправить ключ удаленному провайдеру. В классе WeatherConfig вы можете добавить свой ключ:

1
config.ApiKey=your_key

Это все.

Способствовать

Исходный код библиотеки бесплатный, так что все, кто хочет внести свой вклад в библиотеку, приветствуются. Если вы хотите внести свой вклад в библиотеку, вы можете использовать github и получить новый запрос, чтобы я мог объединить ваш код. Если вы обнаружите ошибки в коде, вы можете открыть вопрос на github или связаться со мной.

Если вы используете библиотеку и вас это устраивает, я бы хотел, чтобы вы отправили несколько скриншотов созданного вами приложения. Вы можете присоединиться к сообществу g + и опубликовать здесь скриншоты, вы можете присоединиться к сообществу, если вы хотите просто высказать свое мнение или предложить некоторые улучшения.

Если кто-то хочет внести свой вклад в библиотеку, предоставив красивый логотип, я был бы очень рад.

Я знаю, что у некоторых пользователей возникли проблемы с импортом библиотеки в Eclipse, если кто-то уже сделал это и хочет объяснить это, вы можете внести свой вклад.