Учебные материалы

Взаимодействие RESTful-сервиса с Spring for Android

Этот урок освещает процесс создания приложения, которое использует Spring For Android RestTemplate для взаимодействия с MVC RESTful web-сервисом.

Что вы создадите

Вы создадите Android-клиент, который взаимодействует с Spring RESTful web-сервисом. В частности, клиент будет взаимодействовать с сервисом, созданным в уроке Создание RESTful Web-сервиса.

Android-клиент будет доступен через Android эмулятор и будет взаимодействовать с сервисом через запрос на:

http://rest-service.guides.spring.io/greeting

Сервис будет отвечать JSON сообщением:

{"id":1,"content":"Hello, World!"}

Android-клиент будет отображать ID и содержимое в форме.

Что вам потребуется

  • Примерно 15 минут свободного времени
  • Android Studio
  • Интернет соединение

Создание Android-проекта

Создайте в Android Studio новый проект. Если хотите, можете использовать проект из каталога initial и перейти к шагу Создание класса представления. Когда вы закончите, то сможете сравнить ваш код с кодом из каталога complete и запустить клиент. Используйте "Rest" для приложения и имен модуля, а также измените имя пакета на "org.hello.rest". Укажите местоположение вашего проекта и оставьте остальные параметры как есть по умолчанию.

Создание нового проекта

Следующий скрин отображает некоторые параметры для настройки иконок приложения. Оставьте как есть по умолчанию.

Создание нового проекта

Следующий скрин отображает параметры для выбора типа используемого activity. Выберите "Blank Activity".

Создание нового проекта

Последний скрин отображает некоторые каталоги для настроек activity, разметки и имени фрагмента. И снова оставьте как есть настройки по умолчанию и нажмите кнопку "Finish".

Создание нового проекта

Когда вы создадите проект, вы увидите, что добавлены несколько файлов.

View the Android project contents

Для прохождения этого урока, вам предстоит отредактировать следующие файлы:

  • Rest/src/main/AndroidManifest.xml
  • Rest/src/main/res/values/strings.xml
  • Rest/src/main/res/layout/fragment_main.xml
  • Rest/src/main/res/menu/main.xml
  • Rest/build.gradle
  • Rest/src/main/java/org/hello/rest/MainActivity.java

Создание Android Manifest

После того, как вы создали проект, AndroidManifest.xml был также создан в базовом исполнении. Android Manifest содержит всю необходимую информацию для запуска Android-приложения и не может быть собрано без него. Манифест также содержит любые разрешения, которые приложение запрашивает у операционной системы Android. В нашем случае, приложению необходим доступ к интернет для создания HTTP запросов.

Добавьте INTERNET разрешение, чтобы приложение могло получить доступ к ресурсам через интернет.

Rest/src/main/AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="org.hello.rest"
    android:versionCode="1"
    android:versionName="1.0">

    <uses-sdk
        android:minSdkVersion="7"
        android:targetSdkVersion="19" />

    <uses-permission android:name="android.permission.INTERNET" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme">
        <activity
            android:name="org.hello.rest.MainActivity"
            android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

Создание строковых ресурсов

Текстовые строки могут ссылаться на файловые ресурсы как из приложения, так и на другие источники. В этом уроке изпользуются четыре текстовых представления и пункт меню, где каждый из этих UI элементов нуждается в тектовом описании. Для начала, удалите строки hello_world и action_settings. Они не используются в этом учебном материале, поэтому могут быть удалены. Затем добавьте строки id_label, id_value, content_label, content_value и action_refresh для каждого UI виджета на будущее.

Rest/src/main/res/values/strings.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>

    <string name="app_name">Rest</string>
    <string name="id_label">The ID is</string>
    <string name="id_value">[id]</string>
    <string name="content_label">The Content is</string>
    <string name="content_value">[content]</string>
    <string name="action_refresh">Refresh</string>

</resources>

Создание разметки

Файл разметки является местом, где вы определяете визуальную структуру пользовательсткого интерфейса вашего приложения. Когда вы создали проект, Android Studio добавило фрагмент разметки. Как следует из названия, фрагмент разметки представляет собой часть общей разметки. В нашем случае, фрагмент разметки использован для отображения некоторого текста в главном activity. Удалите существующий "Hello world" TextView, который был добавлен автоматически изначально при создании проекта. Затем измените фрагмент разметки, включив в него четыре TextView виджета.

Rest/src/main/res/layout/fragment_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin"
    tools:context=".MainActivity$PlaceholderFragment">

    <TextView
        android:id="@+id/id_label"
        android:text="@string/id_label"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <TextView
        android:id="@+id/content_label"
        android:text="@string/content_label"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="25dp"
        android:layout_below="@+id/id_label"
        android:layout_alignParentLeft="true" />

    <TextView
        android:id="@+id/id_value"
        android:text="@string/id_value"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_toRightOf="@+id/id_label"
        android:layout_marginLeft="50dp" />

    <TextView
        android:id="@+id/content_value"
        android:text="@string/content_value"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignTop="@+id/content_label"
        android:layout_alignLeft="@+id/id_value" />

</RelativeLayout>

Разметка включает некоторую информацию о расположении и размере виджетов. Android Studio отображает визуальное представление разметки в окне предварительного просмотра:

Fragment layout preview

Создание меню

Проект содержит меню для главного activity с существующим пунктом "Settings". Удалите этот пункт и добавьте пункт "Refresh". Обратите внимание, что для значения пункта меню также используется строковый ресурс.

Rest/src/main/res/menu/main.xml

<menu xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    tools:context=".MainActivity" >

    <item android:id="@+id/action_refresh"
        android:title="@string/action_refresh"
        android:orderInCategory="100"
        app:showAsAction="never" />
</menu>

Android Studio отображает визуальное представление разметки в окне предварительного просмотра:

Fragment layout preview

Создание класса представления

По медели JSON данных, полученных из RESTful HTTP запроса, вам необходимо создать класс представления, который определяет поля. Перейдите в "org.hello.rest" пакет из панели Project. Выберите "New..." из меню "File".

Добавление нового файла

Выберите "Java Class"

Добавление нового класса

Добавьте переменные id и content, а также их методы получения(getters).

Rest/src/main/java/org/hello/rest/Greeting.java

package org.hello.rest;

public class Greeting {

    private String id;
    private String content;

    public String getId() {
        return this.id;
    }

    public String getContent() {
        return this.content;
    }
}

Добавление зависимостей

Чтобы использовать Spring for Android RestTemplate, вам необходимо добавить соответсвующие Maven зависимости в файл сборки Gradle. RestTemplate позволяет использовать Jackson, мощный JSON обработчик для Java.

Возможно, вам потребуется закрыть и заново открыть Android Studio, чтобы Gradle правильно обновил зависимости.

Rest/build.gradle

apply plugin: 'android'

android {
    compileSdkVersion 19
    buildToolsVersion "19.0.3"

    defaultConfig {
        minSdkVersion 8
        targetSdkVersion 19
        versionCode 1
        versionName "1.0"
    }
    buildTypes {
        release {
            runProguard false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
        }
    }
    packagingOptions {
        exclude 'META-INF/ASL2.0'
        exclude 'META-INF/LICENSE'
        exclude 'META-INF/license.txt'
        exclude 'META-INF/NOTICE'
        exclude 'META-INF/notice.txt'
    }
}

dependencies {
    compile 'com.android.support:appcompat-v7:+'
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'org.springframework.android:spring-android-rest-template:1.0.1.RELEASE'
    compile 'com.fasterxml.jackson.core:jackson-databind:2.3.2'
}

Создание activity

Шаблон проектирования Model-View-Controller(MVC) широко используется в Android приложениях. Activity управляет представлением, которое является разметкой, уже созданной вами. Когда вы создали проект, MainActivity было создано с реализацией по умолчанию. Измените его, чтобы совершать RESTful HTTP запросы и обновлять представление. Каждое изменение пояснено ниже.

Rest/src/main/java/org/hello/rest/MainActivity.java

package org.hello.rest;

import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v7.app.ActionBarActivity;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.web.client.RestTemplate;

public class MainActivity extends ActionBarActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        if (savedInstanceState == null) {
            getSupportFragmentManager().beginTransaction()
                    .add(R.id.container, new PlaceholderFragment())
                    .commit();
        }
    }

    @Override
    protected void onStart() {
        super.onStart();
        new HttpRequestTask().execute();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {

        // Заполнение меню; добавляются пункты меню в action bar, если он присутствует.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Это обработчик нажатия на пукт меню action bar. Аction bar будет
        // автоматически обрабатывать нажатия Home/Up кнопки, до тех пор
        // пока вы вы определите их действия в родительском activity в AndroidManifest.xml.
        int id = item.getItemId();
        if (id == R.id.action_refresh) {
            new HttpRequestTask().execute();
            return true;
        }
        return super.onOptionsItemSelected(item);
    }

    /**
     * Фрагмент, содержащий простое представление.
     */
    public static class PlaceholderFragment extends Fragment {

        public PlaceholderFragment() {
        }

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
            View rootView = inflater.inflate(R.layout.fragment_main, container, false);
            return rootView;
        }
    }


    private class HttpRequestTask extends AsyncTask<Void, Void, Greeting> {
        @Override
        protected Greeting doInBackground(Void... params) {
            try {
                final String url = "http://rest-service.guides.spring.io/greeting";
                RestTemplate restTemplate = new RestTemplate();
                restTemplate.getMessageConverters().add(new MappingJackson2HttpMessageConverter());
                Greeting greeting = restTemplate.getForObject(url, Greeting.class);
                return greeting;
            } catch (Exception e) {
                Log.e("MainActivity", e.getMessage(), e);
            }

            return null;
        }

        @Override
        protected void onPostExecute(Greeting greeting) {
            TextView greetingIdText = (TextView) findViewById(R.id.id_value);
            TextView greetingContentText = (TextView) findViewById(R.id.content_value);
            greetingIdText.setText(greeting.getId());
            greetingContentText.setText(greeting.getContent());
        }

    }

}

Для начала, добавьте частный класс HttpRequestTask. Этот класс наследуется от AsyncTask, который представляет собой механизм Android для выполнения потенциальных, долговременных действий вне главного UI потока. Это очень важно, т.к. иначе вы бы заблокировали UI, вынуждая пользователя поверить в то, что приложение не отвечает или завершилось с ошибкой.

Spring предоставляет шаблонный класс RestTemplate. Он позволяет взаимодействовать с большинством RESTful сервисами. В методе doInBackground класса HttpRequestTask, RestTemplate использован для создания HTTP запроса и разбора JSON ответа в Greeting объект. Когда doInBackground заканчивается, вызывается метод onPostExecute, в котором текстовые значения виджетов greetingIdText и greetingContentText обновляются результатом HTTP запроса.

Далее, добавьте метод onStart с вызовом метода execute класса HttpRequestTask. Метод onStart является частью жизненного цикла Activity и вызывается при запуске activity. В результате, HTTP запрос выполнится, когда приложение загружается.

Напоследок, обновите метод onOptionsItemSelected, чтобы также выполнять HTTP запрос, когда пункт меню "Refresh" выбран. Это позволяет вам совершать дополнительные HTTP запросы без необходимости закрывать и перезапускать приложение.

Запуск клиента

Теперь вы можете запустить приложение из Android Studio. Для этого нажмите кнопку проигрывателя(зеленый треугольник) на панели инструментов Android Studio. Перед вами откроется диалоговое окно с выбором устройства, на котором будет запущено приложение. У вас должно быть Android-устройство, либо эмулятор, настроенный для запуска приложения. Если у вас нет настроенного Android Virtual Device (AVD), то вы можете выбрать кружочек для создания нового.

Выбор Android устройства

После выбора устройства, Android Studio соберет и развернет приложение:

Model data retrieved from the REST service is rendered into the view

ID значение будет увеличиваться каждый раз при нажатии кнопки обновления в меню.

Model data retrieved from the REST service is rendered into the view

Итог

Поздравляем! Вы только что разработали простой REST-клиент, используя Spring for Android.

С оригинальным текстом урока вы можете ознакомиться на spring.io.

comments powered by Disqus