Автор оригинала: Haider Khan.
Улучшение на 67,1% в производительности
Таким образом, вы хотите создать приложение для Android, но застряли на стороне клиента API, не уверены в том, как действовать с обработкой запросов и ответов от API?
Нет ни одного наилучшего способа справиться с этой проблемой, так как Android не является сервером боковой базы, такой как Узел. JS или Рубин на рельсах Там нет установленной политики вокруг внедрения бокового кода RESTFLAY клиента для приложения Android.
На первый взгляд нам нужно будет выяснить, какие API для тестирования. Я выбрал Прогноз .IO API, который проста и простой в настройке. Перейти к этому URL здесь, и вы увидите экран так:
https://developer.forecast.io/register
Зарегистрируйтесь для учетной записи, и вы будете продолжить страницу, предоставляя вам ваш ключ API. Вам будет уделено URL-адрес MOCK с координатами Mock Lastity и Longitude, идите вперед и нажмите на него, чтобы просмотреть ответ JSON, с которой вы будете работать. Вы увидите что-то вроде этого:
{ latitude: 37.8267, longitude: -122.423, timezone: "America/Los_Angeles", offset: -7, currently: { time: 1435372205, summary: "Partly Cloudy", icon: "partly-cloudy-day", nearestStormDistance: 0, precipIntensity: 0, precipProbability: 0, temperature: 60.79, apparentTemperature: 60.79, dewPoint: 54.52, humidity: 0.8, windSpeed: 12.5, windBearing: 251, visibility: 8.6, cloudCover: 0.5, pressure: 1012.62, ozone: 303.25 }, ... }
Мы захочем получить сводный ключ в этом вложенном объекте JSON под названием «В настоящее время» Отказ
Неправильный путь
(Вы будете ценить правильный путь больше)
В ближайшее время нам нужно будет создать проект, чтобы открыть Android Studio и создать проект под названием WeatherApp. Внутри вашего МАЯТАКТИВНОСТЬ.ЯВА Класс Создайте следующие переменные (убедитесь, что вставьте собственную клавишу API для API_KEY):
private static final String TAG = MainActivity.class.getSimpleName(); private static final String BASE_URL = "https://api.forecast.io/forecast/"; private static final String API_KEY = " *******************************"; private static final double LATITUDE = 37.8267; private static final double LONGITUDE = -122.423; private TextView mSummary; private Button mGetButton;
API_URL — это URL-адрес, который нам нужно будет ударить, чтобы сделать запросы, а API_KEY — это ключ, представленный вам после регистрации. Внутри Activity_main.xml Создайте следующую кнопку и TextView:
Вы должны увидеть что-то вроде этого:
Если вы не видите это или он дает вам ошибки компиляции, попробуйте переключить версию Android на вкладке «Предварительный просмотр». Движение вперед, мы подключаем наш взгляд и прикрепите слушателя
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mSummary = (TextView) findViewById(R.id.summary); mGetButton = (Button) findViewById(R.id.weatherButton); mGetButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { new WorkerTask().execute(); } }); }
Мы захочу создать Асинктюз Класс, чтобы обработать сеть в рабочей нити, поэтому создайте следующее внутри MainActivity.java :
private class WorkerTask extends AsyncTask{ @Override protected void onPreExecute() { super.onPreExecute(); } @Override protected String doInBackground(Void... params) { return null; } @Override protected void onPostExecute(String s) { super.onPostExecute(s); } }
Давайте использовать класс под названием Httpurlconnection Чтобы отправить запрос на получение прожекторов. API (убедитесь, что у вас есть Android.Permission. Интернет в списке в вашем манифесте). Это может быть достигнуто со следующим кодом:
@Override protected String doInBackground(Void... params) { try { URL url = new URL(ForecastClient.API_URL + "/" + Double.toString(LATITUDE) + "," + Double.toString(LONGITUDE)); HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection(); urlConnection.setRequestMethod("GET"); urlConnection.connect(); int status = urlConnection.getResponseCode(); switch (status) { case 200: BufferedReader br = new BufferedReader(new InputStreamReader(urlConnection.getInputStream())); StringBuilder sb = new StringBuilder(); String line; while ((line = br.readLine()) != null) { sb.append(line + "\n"); } return sb.toString(); } } catch (Exception e) { e.printStackTrace(); } return null; }
Добавьте следующие операторы журнала под OnPostexecute ():
@Override protected void onPostExecute(String s) { super.onPostExecute(s); Log.d(TAG, s); }
Большой! Теперь вы должны получать такое ответа:
Мы захотим преобразовать строку JSON в Побуждать Объект, использующий Jsonobject. . Мы можем выполнить это, используя следующий код, обратите внимание, что я собираюсь во время вложенного в настоящее время json json, а затем захватываю значение ключа «Резюме» (посмотрите на ответ JSON, который я опубликовал выше):
@Override protected void onPostExecute(String s) { super.onPostExecute(s); try { JSONObject weatherJSON = new JSONObject(s); JSONObject currentlyJSON = weatherJSON.getJSONObject("currenlty"); mSummary.setText(currentlyJSON.getString("summary")); } catch (JSONException e) { e.printStackTrace(); } }
Теперь ваше приложение должно обновить TextView соответственно:
Большой!! У нас есть наше приложение, отправляющее запросы на службу API, и мы можем получить данные обратно и обновить наши UI!
Мы должны быть сделаны правильно?
Не так. Представьте себе прикрепление всех тех, кто попробуйте выявить заявления и писать все эти асинктюды для обработки нескольких вызовов на API для масштабируемого приложения! Это было бы головной болью! Также получение ценностей от объекта POJO станет кошмаром достаточно сложности. Большинство наших классов (мероприятия и т. Д.), которые будут раздутыми сетевыми запросами.
Правильный путь
Мы собираемся использовать Модернизация , GSON и Отто обрабатывать сеть, сериализацию JSON/дезерриализацию и асинхронные события.
Отказ от ответственности: GNON, как показано, медленнее в сериализации/десериализации по сравнению с прокасом собственной пользовательской библиотеки. Хотя GSON — это приятно использовать, я рекомендую катиться своим собственным. Для целей этого учебника мы собираемся использовать GSON, чтобы сэкономить время.
Сначала давайте схватим зависимости для сторонних библиотек:
compile 'com.squareup.retrofit:retrofit:1.9.0' compile 'com.squareup:otto:1.3.8' compile 'com.squareup.okhttp:okhttp:2.4.0' compile 'com.google.code.gson:gson:2.3'
Вы захотите добавить эти зависимости в файл build.gradle в папке приложения (или на мобильном, если у вас есть модуль износа).
Отлично сейчас мы можем начать! Давайте настроим наш сетевой клиент, создайте пакет под названием API и при этом создать класс под названием ProcessClient.java. Вот так:
Внутри нашего класса прогнозирования мы реализуем Модернизация! Модернизация использует класс под названием Restadapter Чтобы обработать сеть, он в основном интерфейс для API для отдыха. Это использует заводскую или построитель, чтобы создать свой адаптер для обработки сетей. Есть встроенные методы, уже определенные для операций CRUD. Вы можете использовать специальный клиент (хотя вы не связаны с этим клиентом) под названием OkClient с okhttpclient Чтобы обрабатывать тайм-ауты, размеры загрузки и других проблемных сетевых вызовов автоматически. Действительно отличный инструмент! Restadadaper использует .create (класс
Мы реализуем рисунок Singleton в нашем клиенте, так что для наших сетевых звонков есть только один адаптер:
public class ForecastClient { private static final String BASE_URL = "https://api.forecast.io/forecast/"; private static final String API_KEY = " *************************"; public static final String API_URL = BASE_URL + API_KEY; private static ForecastClient mForecastClient; private static RestAdapter mRestAdapter; public static ForecastClient getClient() { if (mForecastClient == null) mForecastClient = new ForecastClient(); return mForecastClient; } private ForecastClient() { mRestAdapter = new RestAdapter.Builder() .setEndpoint(API_URL) .setClient(new OkClient(new OkHttpClient())) .setLogLevel(RestAdapter.LogLevel.FULL) .build(); } }
.Стролью это вложенный внутренний класс внутри Restadapter и имеет методы . netseendpoint, .SetClient и .Build . Сокращение, как вы, возможно, угадаете создает объект URL API из строки. SetClient Устанавливает ваш клиент, есть разные типы клиентов, которые могут поддерживать Ressadapter, но на данный момент мы просто будем использовать Okhttp. построить Метод возвращает новый RestadaDapter. С нашим методом Singleton GetClient. Мы когда-либо делаем только один клиент. Я также глян в другие функции, такие как обстановка Requestiverector Если API включает в себя ОАУТ.
Теперь давайте перейдем к созданию наших Отто автобус . Мы создаем пакет под названием Автобус и внутри этого мы создаем класс под названием Busprovider.java :
Детали этого класса будут выглядеть так:
public final class BusProvider { private static final Bus BUS = new Bus(ThreadEnforcer.ANY); public static Bus getInstance() { return BUS; } private BusProvider() { } }
Мы хотим запретить наследование этого класса по соображениям безопасности, поэтому мы добавляем Финал ключевое слово. Отто обычно отправляет события на основной нитью приложения, и обычно, если вы хотите, чтобы это поведение мы установим ThreadenForcer к .ГЛАВНЫЙ Однако иногда мы можем опубликовать события в фоновом потоке, по этой причине мы устанавливаем Threeprcercer — любой Отказ Уведомление о том, что у нас здесь есть шаблон синглтон, имел ли смысл иметь несколько автобусов?
Теперь мы хотим создать класс менеджера, давайте назовем это Прогнознаджер.java Это будет наш центральный центр для получения и отправки событий между контроллерами и фоновой деятельностью сети. Давайте создадим другой пакет под названием Менеджер И добавьте этот класс, вроде так:
Давайте перейдем на детали этого класса:
public class ForecastManager { private Context mContext; private Bus mBus; private ForecastClient sForecastClient; public ForecastManager(Context context, Bus bus) { this.mContext = context; this.mBus = bus; sForecastClient = ForecastClient.getClient(); } }
Мы проходим в контексте конструктору своего класса. Это в случае, если нам может потребоваться получить системные услуги или общие предпочтения или что-либо, связанное с контекстом. Это чрезвычайно полезно. У нас есть ссылочная переменная к нашему классу клиента, и у нас есть ссылочная переменная к нашему автобусу OTTO.
Большой!! Но как мы используем этот класс ??? Нам нужно будет создать пользовательский класс приложений и зарегистрировать наш класс Bus и Manager! Продолжай и создайте пакет под названием Приложение и внутри это создать класс под названием Прогнозирование. Ява вот так:
Давайте перейдем к деталям этого таможенного класса Application (не забудьте установить Android: name »» в вашем файле манифеста в разделе <Приложение> на ваш пользовательский класс приложений).
public class ForecastApplication extends Application { private ForecastManager mForecastManager; private Bus mBus = BusProvider.getInstance(); @Override public void onCreate() { mForecastManager = new ForecastManager(this, mBus); mBus.register(mForecastManager); mBus.register(this); } }
Мы создаем новый Прогнозным прогнозированием класс, а также захватывающий наши Автобус объект из Busprovider.java класс, который мы определили ранее. Это все происходит при запусках приложения, и только один раз! Потрясающие! Далее мы проходим в контексте приложения и автобус до менеджера и зарегистрируем менеджер в автобус. Объект автобуса имеет карта и Установить Объекты в нем к ключу в классах, которые вы регистрируете в автобусе. Это может означать, что вы можете зарегистрировать услуги, мероприятия, интенсивные сервисы и т. Д. В автобус. Затем автобус отслеживает эти классы для любых событий, которые отправляются или получены. Очень очень удобно.
Отлично мы зарегистрировали наш менеджер и наш автобус к заявке, но где Сексуальный код Чтобы обработать вызовы API?! Теперь это то, где модернизация действительно сияет. Чтобы обработать сетевые звонки, нам нужно создать наши Побуждать Сначала объекты, давайте построим некоторые модели модели с GSON !
Посмотрите на ответ JSON от API PrograStast.io, нам нужно будет строить модели, чтобы соответствовать этим данным. В частности, мы ищем только «в настоящее время» вложенного объекта JSON во-первых, нам нужно:
Красота GSON в том, что нам не нужно модифицировать StringBuilder или Jsonobjects обрабатывать анализ запросов или ответов JSON. Мы можем просто создать наши модели классов и добавить аннотацию @Serializedname («key_value») на вершину переменной. Позвольте мне показать вам, как это работает.
Давайте создадим модели пакет внутри нашего API Пакет, вы должны увидеть что-то вроде этого (не обращайте внимания на пакет интерфейсов на данный момент, мы доберемся до этого!)
Теперь давайте сделаем наши Weather.java модель класса.
public class Weather { @SerializedName("currently") private Currently mCurrently; public Currently getCurrently() { return mCurrently; } }
@Serializedname («В настоящее время») Принимает вложенный объект JSON «В настоящее время» и преобразует его в объект. Что такое В настоящее время объект, который вы спрашиваете? В настоящее время представляет наш вложенный объект JSON, нам нужно будет создать другой класс модели на данный момент. Также обратите внимание, я ухожу много данных из ответа JSON. Вы Может Добавьте переменные для всех этих атрибутов, если вы хотите, но для целей этого учебника нам понадобится только сводный ключ внутри в настоящее время. Давайте сделаем наши В настоящее время.java класс:
public class Currently { @SerializedName("time") private long mTime; public long getTime() { return mTime; } @SerializedName("summary") private String mSummary; public String getSummary() { return mSummary; } }
Красота здесь заключается в том, что GSON автоматически создает все объекты POJO для вас, все, что вам нужно сделать, это позвонить методам Getter, и вы устанавливаете !!! КЛАССНО!!!
Теперь, когда у нас есть наши модели, нам нужно будет реализовать обратные вызовы на Restadapter на самом деле захватить наш ответ JSON. Модернизация нуждается в интерфейсах, которые будут передаваться в Restadapter ‘s .create (…) метод. Давайте создадим этот пакет под названием интерфейсы Теперь и добавьте наш интерфейс погоды:
Внутри Iweather Мы пишем следующее:
public interface IWeather { @GET("/{latitude},{longitude}") void getWeather(@Path("latitude") String latitude, @Path("longitude") String longitude, Callbackcallback); }
Можете ли вы визуализировать, что здесь происходит? Мы строим URL на нашем API_URL. Нам не нужно устанавливать метод запроса, мы можем просто использовать аннотацию @Get (…), а также модифицированные ручки @POST (…) и другие операции. Аннотация @path заменяет текст внутри кронштейнов {..}. Мы можем просто пройти в нашу долготу, широту и обратный вызов. Что этот обратный вызов, который вы спрашиваете? Модернизация Обратный вызов
Теперь давайте выпишем нашу реализацию для GetWeater. внутри ProcessClient.java. (Вы можете реализовать эти методы где-то еще, чтобы отделить вещи еще больше, но для целей этого учебника мы просто реализуем его там):
public void getWeather(String latitude, String longitude, Callbackcallback) { IWeather weather = mRestAdapter.create(IWeather.class); weather.getWeather(latitude, longitude, callback); }
Этот метод вызывает .create (…) Метод от Restadapter Класс, как упоминалось ранее, и создает услугу API для нас. Все, что нам просто нужно сделать сейчас, называется нашим интерфейсным методом _.getweather (… ) _ и пройти в параметрах для нашего запроса. На самом деле реализовать этот метод и использовать его, мы будем называть его от нашего объекта клиента в классе Manager, как так:
@Subscribe public void onGetWeatherEvent(GetWeatherEvent getWeatherEvent) { String latitude = Double.toString(getWeatherEvent.getLatitude()).trim(); String longitude = Double.toString(getWeatherEvent.getLongitude()).trim(); Callbackcallback = new Callback () { @Override public void success(Weather weather, Response response) { // Handle Weather } @Override public void failure(RetrofitError error) { // Handle Failure } }; sForecastClient.getWeather(latitude, longitude, callback); }
Поскольку наш класс Manager зарегистрирован в автобус, автобус тогда Подписки к событиям, которые являются Опубликовано на его нить. Мы используем следующий рисунок.
bus.post (новое событие ());
Тогда в другом классе мы реализуем следующее:
@Subscribe> Публичная пустота OneVent (событие события) {//сделать что-то}
Отто слушает это событие под аннотацией @subscribe. Вы можете увидеть, как это делает события (например, пользователь, запрашивая информацию от API), легко обрабатывать! ОТЛИЧНО!!
Также примите к сведению обратный вызов, который мы на самом деле создаем Обратный вызов
Теперь нам нужно на самом деле позвонить в это событие, чтобы сделать, чтобы мы должны зарегистрировать наши МАЯТАКТИВНОСТЬ.ЯВА Класс с автобусом, поэтому он может отправлять и получать события из автобуса. Мы реализуем это таким образом:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mSummary = (TextView) findViewById(R.id.summary); mGetButton = (Button) findViewById(R.id.weatherButton); mGetButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { } }); } @Override public void onResume() { super.onResume(); mBus.register(this); } @Override public void onPause() { super.onPause(); mBus.unregister(this); }
Мы хотим зарегистрировать деятельность, когда активность возобновляется, и отменить регистрацию, когда деятельность паузы. Почему мы это сделаем это? Можете ли вы подумать о любых проблемах, к которым приложение может столкнуться, если мы не запустили его таким образом?
Отлично, мы почти закончили, нам просто нужно отправить мероприятие в наш менеджер сейчас! Давайте сделаем это, публикуя событие на автобус внутри Mggebutton’s Нажмите Lisserver, как так:
mGetButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { mBus.post(new GetWeatherEvent(LATITUDE, LONGITUDE)); } });
Мы просто проходим на нашу широту и долготу класса GetWeathervent. Отто прослушивает этот класс подписан на менеджер и выполняет запрос API To Process. API. Просто и красиво.
GetWeatherevent.java Класс выглядит так:
public class GetWeatherEvent { private double mLatitude; private double mLongitude; public GetWeatherEvent(double latitude, double longitude) { this.mLatitude = latitude; this.mLongitude = longitude; } public double getLatitude() { return mLatitude; } public double getLongitude() { return mLongitude; } }
Мы сократили наш раздутый МАЯТАКТИВНОСТЬ.ЯВА до ~ 10 строк дополнительного кода вместо ~ 40 строк. Автобус опубликует менеджер менеджеру, а затем на успешном запросе мы можем отправить обратно событие на MainActivity.java вот так:
@Subscribe public void onGetWeatherEvent(GetWeatherEvent getWeatherEvent) { String latitude = Double.toString(getWeatherEvent.getLatitude()).trim(); String longitude = Double.toString(getWeatherEvent.getLongitude()).trim(); Callbackcallback = new Callback () { @Override public void success(Weather weather, Response response) { mBus.post(new SendWeatherEvent(weather)); } @Override public void failure(RetrofitError error) { } }; sForecastClient.getWeather(latitude, longitude, callback); }
Sendweatherevent.java это простой класс с конструктором и добытелем для Погода объект:
public class SendWeatherEvent { private Weather mWeather; public SendWeatherEvent(Weather weather) { this.mWeather = weather; } public Weather getWeather() { return mWeather; } }
Мы можем тогда Подписаться на это событие в нашем МАЯТАКТИВНОСТЬ.ЯВА класс, а также установите резюме к TextView! Вот так:
@Subscribe public void onSendWeatherEvent(SendWeatherEvent sendWeatherEvent) { Weather weather = sendWeatherEvent.getWeather(); Currently currently = weather.getCurrently(); mSummary.setText(currently.getSummary()); }
Красивый и простой.
Чтобы получить вывод журнала, мы можем добавить следующее в нашу Restadapter объект:
private ForecastClient() { mRestAdapter = new RestAdapter.Builder() .setEndpoint(API_URL) .setClient(new OkClient(new OkHttpClient())) .setLogLevel(RestAdapter.LogLevel.FULL) .build(); }
LogLevel может быть установлен на .none, .banic, или .full Чтобы увидеть, что ваш адаптер запрашивается и получает. Вы можете увидеть весь запрос JSON в Logcat, так же, как если бы вы делали Curl Команда!
Весь шаблон выглядит так:
Пользователь нажимает кнопку → МИНУТАКТИВНОСТЬ → GetWeatherevent → Manager → Client → Manager → Sendweatherevent → МИНУТАКТИВНОСТЬ → Пользователь видит резюме
Вот тесты модернизации + Otto против асинкт-асинкт-асинктюз:
Улучшение на 67,1% над асинктюдой
Вот и все! Надеюсь, ты повеселишься. Это настоящая красота, чтобы смешать Отто + модернизацию. Используя этот шаблон выше, через мои собственные исследования на Android я смог уменьшить сложность кода и увеличить читаемость и реализацию. Еще одна заметка, это поможет абстрагировать события, чтобы вы могли повторно использовать объекты, поскольку создание событий может стать громоздкой. Не стесняйтесь отправить электронное письмо на khan@datalofts.com по любым вопросам. Счастливое потребление API!
Оригинал: «https://www.codementor.io/@zkhaider/retrofit-otto-networking-made-easy-on-android-87pzx7qik»