Эта серия из двух частей познакомит вас с основами работы с веб-сервисами RESTful с помощью Android SDK. Попутно вы узнаете, как выполнять поиск по общедоступному API Twitter!
В этом уроке мы будем использовать AsyncTask для получения твитов JSON, их анализа, а затем отображения в пользовательском интерфейсе. Несмотря на то, что код в этом руководстве относится только к Twitter, применяемые принципы применяются для извлечения многих других веб-каналов и API-интерфейсов с использованием архитектуры RESTful.
Этот учебный курс по Android Twitter Search состоит из двух частей:
Шаг 1. Создайте внутренний класс AsyncTask
Мы собираемся использовать AsyncTask для получения, анализа и отображения ленты твитов в поисковом запросе пользователя. Используя AsyncTask, мы можем перенести обработку в фоновый поток, результаты которого все еще доступны для отображения в интерфейсе приложения. В своем классе Activity добавьте внутренний класс AsyncTask после метода searchTwitter :
1
2
3
|
private class GetTweets extends AsyncTask<String, Void, String> {
}
|
Класс AsyncTask является абстрактным, что означает, что вы должны создать подкласс, чтобы использовать его. Такие подклассы должны реализовывать один конкретный метод, который мы добавим дальше. В то же время, Eclipse будет отображать сообщения об ошибках (пока просто игнорируйте их).
AsyncTask использует три универсальных типа, как вы можете видеть из начальной строки объявления класса. Первый указывает тип параметра — в нашем случае это строка, так как мы собираемся передать созданную нами строку URL. Средний тип предназначен для модулей прогресса, которые мы не будем использовать в этом руководстве, поэтому мы просто указываем void. Единицы прогресса могут использоваться для индикации хода выполнения фоновых задач. Третий тип — это другая строка, которую возвращает фоновый процесс. В нашем случае это будет извлеченный текст фида JSON.
Шаг 2. Выполните фоновую обработку
Внутри вашего класса AsyncTask добавьте следующий метод, который мы переопределяем из родительского класса:
1
2
3
4
|
@Override
protected String doInBackground(String… twitterURL) {
}
|
Тип параметра — строка, соответствующий первому типу, который мы указали в открывающей строке объявления класса. Эта строка будет URL-адресом API поиска в Твиттере, который мы создали в прошлый раз. Внутри этого метода мы указываем, какой фоновый процесс мы хотим выполнить AsyncTask. Метод также возвращает значение типа string, чтобы соответствовать тому, что мы указали в качестве третьего параметра в строке открытия объявления класса. Эта возвращенная строка будет получена в качестве параметра для второго метода, который мы реализуем позже.
Совет: если вы не знакомы с абстрактными классами или универсальными типами, не беспокойтесь — на самом деле мы просто следуем шаблону. Как и для большей части платформы Android, вы можете узнать, как использовать эти ресурсы из примеров в Руководстве разработчика и, в данном случае, Справочника по API .
Шаг 3: Отправить запрос
Результатом поиска в Твиттере будет строка, которую мы будем строить из полученного нами ответа. Внутри метода doInBackground начните с создания String Builder:
1
|
StringBuilder tweetFeedBuilder = new StringBuilder();
|
Хотя мы используем одну строку URL, метод получит массив объектов указанного типа (строка), поэтому давайте пройдемся по нему:
1
2
3
|
for (String searchURL : twitterURL) {
}
|
На самом деле цикл будет повторяться только один раз, но вы можете расширить свой код для получения нескольких поисковых каналов, поэтому сейчас мы будем использовать цикл. Внутри цикла создайте HTTP-клиент для выполнения запроса:
1
|
HttpClient tweetClient = new DefaultHttpClient();
|
Теперь нам нужно отлавливать исключения ввода-вывода, что неизменно имеет место, когда вы пытаетесь получить данные из любого места за пределами вашего приложения. Добавьте блоки try и catch :
1
2
3
4
5
6
7
|
try {
}
catch(Exception e) {
tweetDisplay.setText(«Whoops — something went wrong!»);
e.printStackTrace();
}
|
Если есть ошибка ввода / вывода, мы просто пишем сообщение в пользовательский интерфейс. Внутри блока try создайте объект HTTP Get для выдачи запроса, передав URL-адрес поиска:
1
|
HttpGet tweetGet = new HttpGet(searchURL);
|
Теперь мы можем выполнить запрос и сохранить результаты в объекте HTTP Response:
1
|
HttpResponse tweetResponse = tweetClient.execute(tweetGet);
|
Мы сможем использовать объект ответа для доступа к содержанию и состоянию ответного сообщения, полученного из Twitter.
Шаг 4: обработать ответ
Прежде чем мы попытаемся обработать ответное сообщение, давайте проверим статус. Все еще внутри блока try :
1
|
StatusLine searchStatus = tweetResponse.getStatusLine();
|
Если ответ в порядке, мы можем продолжить и попытаться проанализировать твиты, в противном случае мы выведем сообщение об ошибке пользователю:
1
2
3
4
5
|
if (searchStatus.getStatusCode() == 200) {
}
else
tweetDisplay.setText(«Whoops — something went wrong!»);
|
Внутри блока оператора if теперь мы можем получить HTTP-сущность и содержимое сообщения в качестве входного потока:
1
2
|
HttpEntity tweetEntity = tweetResponse.getEntity();
InputStream tweetContent = tweetEntity.getContent();
|
Теперь мы можем начать вносить содержимое сообщения в программу, используя Reader для входного потока, а не Buffered Reader для управления входящими данными:
1
2
|
InputStreamReader tweetInput = new InputStreamReader(tweetContent);
BufferedReader tweetReader = new BufferedReader(tweetInput);
|
Давайте прочитаем данные по одной строке за раз, добавляя каждую строку в созданный нами String Builder:
1
2
3
4
|
String lineIn;
while ((lineIn = tweetReader.readLine()) != null) {
tweetFeedBuilder.append(lineIn);
}
|
Это будет добавлять в String Builder до тех пор, пока все полученные данные не будут обработаны. Теперь перейдите в конец метода doInBackground , после блока catch — верните строку, в которую мы встроили результаты:
1
|
return tweetFeedBuilder.toString();
|
На этом метод doInBackground завершен — он выполняет выборку твита и импортирует его в приложение, так что теперь мы можем его проанализировать и отобразить.
Шаг 5: Анализ твита JSON
Теперь, когда AsyncTask получил канал твита, мы можем его проанализировать и отобразить в пользовательском интерфейсе приложения. Для этого мы можем реализовать другой метод класса AsyncTask, добавленный после doInBackground , все еще внутри объявления класса AsyncTask:
1
2
3
|
protected void onPostExecute(String result) {
}
|
Обратите внимание, что этот метод получает строковый параметр, который мы указали в качестве третьего типа в строке объявления начального класса и что мы вернули из doInBackground на последнем шаге. Строка — это текст JSON, представляющий последние твиты по запросу пользователя, полученному из Twitter. Нам нужно будет проанализировать этот текст, чтобы получить доступ к содержимому твитов и отобразить их в пользовательском интерфейсе.
Мы будем встраивать текст твита в строку для отображения, поэтому запустите метод onPostExecute , создав еще один String Builder:
1
|
StringBuilder tweetResultBuilder = new StringBuilder();
|
Методы обработки JSON могут генерировать исключения, поэтому добавьте блоки try и catch следующим образом:
1
2
3
4
5
6
7
|
try {
}
catch (Exception e) {
tweetDisplay.setText(«Whoops — something went wrong!»);
e.printStackTrace();
}
|
Здесь вы должны заметить закономерность — как и в любой программе, в которой вы пытаетесь извлекать и обрабатывать внешние данные, вы должны уделять особое внимание обработке потенциальных ошибок.
Внутри блока try создайте объект JSON, передав текстовую строку JSON:
1
|
JSONObject resultObject = new JSONObject(result);
|
Внутри текстовой строки JSON находится массив, содержащий твиты, а также некоторые другие данные — выполните запрос Twitter, вставив URL-адрес поиска в адресную строку браузера, как, например, в прошлый раз:
1
|
http://search.twitter.com/search.json?q=android
|
Возможно, вам придется скопировать и вставить полученный текст в текстовый редактор, чтобы эффективно его прочитать. Если вы посмотрите текст JSON, вы увидите следующий раздел, который отмечает начало массива твитов:
1
|
«results»:[
|
Нам нужно получить этот массив твитов, используя его имя: «results». Получите массив «results» из объекта JSON:
1
|
JSONArray tweetArray = resultObject.getJSONArray(«results»);
|
Теперь мы можем просмотреть твиты и подготовить их к показу.
Шаг 6: итерируйте массив твитов
Если вы снова посмотрите на текст JSON, полученный через браузер (или, необязательно, в Eclipse, если вы запишете его в журнал Android во время работы приложения), вы увидите содержимое, возвращаемое для каждого твита в массиве. В этом уроке мы будем только выписывать имя пользователя аккаунта и содержание самого твита. Вы можете расширить приложение, чтобы включить любую информацию, которую вы хотите. В тексте, возвращаемом из Twitter, имя пользователя представлено как «from_user», а содержимое твита называется «text» — посмотрите на содержимое JSON, чтобы проверить это и узнать, какие еще элементы данных находятся в нем.
В вашем блоке try , после извлечения массива твитов, добавьте цикл for для итерации твитов:
1
2
3
|
for (int t=0; t<tweetArray.length(); t++) {
}
|
Внутри цикла получите каждый элемент в виде объекта JSON:
1
|
JSONObject tweetObject = tweetArray.getJSONObject(t);
|
Теперь извлеките имя пользователя из этого объекта, добавив его в String Builder вместе с дополнительным текстом для отображения:
1
|
tweetResultBuilder.append(tweetObject.getString(«from_user»)+»: «);
|
Класс JSON Object предоставляет метод getString для этой цели; есть также альтернативный метод get . Теперь получите и добавьте содержимое твита:
1
|
tweetResultBuilder.append(tweetObject.get(«text»)+»\n\n»);
|
Шаг 7: Показать результаты
Теперь перейдите к блоку catch внутри метода onPostExecute . Если обработка сработала, мы отображаем результат в текстовом представлении, в противном случае мы отображаем сообщение об ошибке:
1
2
3
4
|
if(tweetResultBuilder.length()>0)
tweetDisplay.setText(tweetResultBuilder.toString());
else
tweetDisplay.setText(«Sorry — no tweets found for your search!»);
|
Наш класс AsyncTask завершен.
Шаг 8: создание и выполнение AsyncTask
У нас есть AsyncTask для выполнения нашей обработки; нам просто нужно позвонить по этому поводу. Вернитесь к вашему методу searchTwitter , внутри блока try и после того, как мы построили строку URL поискового запроса. Создайте экземпляр нового класса AsyncTask и вызовите для него метод execute , передав строку URL:
1
|
new GetTweets().execute(searchURL);
|
Обратите внимание, что мы передаем строку, которую мы указали в объявлении AsyncTask и в методе doInBackground .
Это базовое приложение завершено — вы можете проверить его в эмуляторе и на устройствах Android. Попробуйте это с различными поисковыми запросами, такими как хэштеги. Конечно, вы можете расширить приложение, чтобы отображать больше информации из твитов и даже ссылаться на Twitter по кликам пользователей. При существующем положении вещей пользователь может прокручивать возвращенную ленту твитов и выполнять повторные поиски по своему усмотрению.
Вывод
В этих двух уроках мы изучали получение твитов из API поиска в Twitter. Вы можете использовать те же шаблоны проектирования для извлечения данных из других веб-ресурсов. Если ваши приложения будут включать более сложные, непрерывные процессы извлечения данных, вы можете обратиться к поставщикам контента и, возможно, к услугам, чтобы максимизировать эффективность. Как и в случае любых внешних операций на основе данных, вы не можете предполагать, что получение необходимой информации будет успешным, поэтому необходим уровень обработки ошибок. Возможность доступа к интернет-данным, безусловно, является одним из ключевых преимуществ мобильных вычислений, поэтому эти методы являются жизненно важным компонентом в наборе инструментов любого разработчика Android.