Урок 15. Знакомство с HTTP. HtppUrlConnection, метод для считывания данных о пользователе – Devcolibri – Android для начинающих

Урок 15. Знакомство с HTTP. HtppUrlConnection, метод для считывания данных о пользователе

Знакомство с HTTP

Для обмена сообщениями с сервером мы будем использовать протокол HTTP. Это очень знаменитый протокол, который используются в модели клиент-серверной архитектуры. Более подробное описание протокола вы можете посмотреть здесь.

Для того, чтобы использовать этот протокол нам необходимо знать адрес сервера, для того, чтобы отправлять запросы.

Все методы, которые предоставляет twitter-api описаны здесь. Обычно все методы, которые предоставляет какой-то компонент называют API. Далее я буду использовать этот термин.

Мы сегодня напишем запрос для метода users.show. Этот метод позволит нам отобразить информацию о пользователе.

Давайте прочитаем документацию метода.

 

UsersShowOverview.png

 

Мы можем увидеть, что:

  • Этот метод имеет тип GET, что означает, что мы считываем информацию.
  • Метод называется users/show. Это указано после слова GET.
  • Для запроса нам надо передать серверу параметр user_id или screen_name. Мы воспользуемся параметром user_id, т.к. мы передаём его на экран UserInfoActivity.
  • Видим адрес для запроса https://api.twitter.com/1.1/users/show.json. Нам надо точно его знать, чтобы мы могли послать запрос по нужному адресу и получить ответ.

В блоке ResourceInformation видим:

 

ResourceInformation.png

 

  • Response formats – JSON. Указывает, что сервер отвечает в формате JSON. Об этом формате мы поговорим в следующем уроке.
  • Requires authentication? Yes. Указывает, что метод требует авторизацию пользователя.
  • Rate limited? Yes. Указывает, что есть ограничения по количеству запросов.
  • Requests / 15-min window (user auth) – 900. Указывает, что можно посылать не более, чем 900 запросов в 15 минут для авторизованного пользователя (наш случай).
  • Requests / 15-min window (app auth) – 900. Указывает, что можно посылать не более, чем 900 запросов в 15 минут для авторизованного приложения (не наш случай). Есть отдельная авторизация, как приложения, при которой не надо указывать данные пользователя. Мы её не будем использовать, т.к. она добавляет дополнительные ограничения.

Следующий блок Parameters:

 

ParametersInfo.png

 

  • user_id – id пользователя информацию о котором мы хотим получить. Поле отмечено как required (обязательное).
  • screen_name – это имя, которое отображается в каждом аккаунте. Оно тоже отмечено, как required (обязательное).
  • include_entities – boolean, значение, которое описывает конфигурацию ответа. Если передаём значение true, то сервер добавит в ответ объект entities с дополнительными вложенными объектами. Поле отмечено как optional(опциональное). Т.е. мы можем его не передавать.

С этим разобрались. Нам для запроса надо передать параметром либо user_id, либо screen_name. Эти параметры мы будем передавать как часть запроса (query params).

В блоке Example Requests на картинке мы видим запрос GET https://api.twitter.com/1.1/users/show.json?screen_name=twitterdev. Давайте разберём его по частям:

  • GET – тип метода. Обозначает, что мы считываем данные, а не обновляем их.
  • https://api.twitter.com/1.1/users/show.json – адрес метода. Он должен всегда оставаться в таком виде.
  • ?screen_name=twitterdev – здесь происходит передача параметров для запроса. Это можно понять по знаку ?. Всё, что передаётся после него относится к параметрам в запросе. В данном примере передаётся параметр screen_name, значение его передаётся после знака = (twitterdev).

Давайте попробуем составим наш запрос. В качестве параметра будем передавать user_id, а не screen_name. Допустим, наш id равен 1234. Тогда запрос будет выглядеть так: GET https://api.twitter.com/1.1/users/show.json?user_id=1234. Если мы ходим передать ещё один параметр include_entities, то надо добавить символ & (shift + 7) между параметрами. Запрос с двумя параметрами выглядит так:

GET https://api.twitter.com/1.1/users/show.json?user_id=1234&include_entities=false

Перед тем, как перейти к реализации HTTP в Android остановимся на удобной console для тестирования большинства популярных API (в том числе twitter). С её помощью можно убедиться, что запрос к серверу составлен верно.

Работа с консолью Twitter API

Давайте перейдём по ссылке.

Выглядит консоль так:

 

TwitterConsole.png

 

Обратим внимание на левую часть – там отображаются все методы, которые доступы в Twitter API. В окно ввода Select an API method давайте введём название нашего метода users/show и нажмём, чтобы показать дополнительную информацию и о нём.

 

UsersShow.png

 

После нажатия на метод, видим, что открылось окно, куда надо ввести параметры для запроса.

Вначале надо добавить данные об авторизации, т.к. метод требует авторизацию пользователя.

Для этого давайте нажмём на кнопку в блоке Authentication и выберем пункт OAuth 1.

 

NoAuth.png

 

В контекстном окне нажимаем Sign in with Twitter. В следующем окне нажимаем кнопку Authorize app.

 

AuthApp.png

 

После этого нас перенаправит на сайт консоли и в блоке Authentication появится наша информация об авторизации.

 

AuthCompleted.png

 

Если выбранный до этого метод сбился, то найдите в списке методов users/show и нажмите на него, чтобы перейти в детальную информацию.

Давайте добавим в форму user_id значение 929257819349700608. Это идентификатор аккаунта colibri-tweet, будем использовать его для теста. В нашем реальном приложениии мы будем брать id динамически после авторизации пользователя. После того, как мы ввели значение и нажали кнопку Send, экран выглядит следующим образом:

 

UsersShowResult.png

Блок Request

Давайте обратим внимание в первую очередь на блок Request в левом нижнем углу. Обратим внимание на первые две строки:

  • GET /1.1/users/show.json?user_id=929257819349700608 HTTP/1.1 – информация о запросе. Похоже на то, что мы разбирали до этого. Только адрес сервера выводится не полностью, но это не проблема. Видим, что параметр передаётся после знака ?, как мы уже видели. Также видим, что используется протокол HTTP/1.1
  • Authorization – header , в котором передаётся информация об авторизованном пользователе. Если бы мы не прошли процесс авторизации, то сервер бы ответил нам с ошибкой.

Блок Response

Блок Response находится в правом нижнем углу. Давайте рассмотрим первую строку ответа:

  • HTTP/1.1 200 OK – информация об ответе. HTTP/1.1 – версия протокола, 200 OK – статус ответа сервера, означающий, что запрос успешно обработан. Подробнее о всех статусах HTTP протокола можно почитать здесь

Также пролистаем этот блок в самый низ и увидим сам ответ в формате JSON.

 

ResponseJson.png

Копирование, форматирование ответа от сервера

В таком виде ответ не годится для понимания. Чтобы выделить всю строку целиком, давайте выделим начало строки и нажмём кнопки shift + end. После этого копируем выделенную строку и переходим на сайт форматирования JSON. Например на этот. Вставляем скопированную строку в левую область экрана и нажимаем кнопку Beautify

 

JsonBeautifier.png

 

Это и есть ответ, который нам послал сервер.

Давайте теперь попробуем повторить эти же самые действия, только в нашем приложении, используя java код.

Использование HttpUrlConnection.

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

Давайте создадим новый пакет, который назовём network. Создадим класс HttpClient, добавим в него один метод, который назовём readUserInfo(long userId).

Реализация выглядит так:

 

HtppClient.java

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
package colibri.dev.com.colibritweet.network;

import colibri.dev.com.colibritweet.pojo.User;

public class HttpClient {

    public String readUserInfo(long userId) {
        return null;
    }
}

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

Первое, что нам надо сделать – это составить адрес запроса в формате, описанном выше. Он должен выглядеть следующим образом: https://api.twitter.com/1.1/users/show.json?user_id=1234. Нам необходимо динамически подставлять в запрос userId, который поступает в метод параметром. Теперь наш метод выглядит так:

 

HtppClient.java

1
2
3
4
5
6
7
public class HttpClient {

    public String readUserInfo(long userId) {
        String requestUrl = "https://api.twitter.com/1.1/users/show.json?user_id=" + userId;
        return null;
    }
}

 

Теперь нам надо отправить запрос серверу по этому адресу.

Отправление запроса серверу

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

 

HtppClient.java

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
public class HttpClient {

    public String readUserInfo(long userId) throws IOException {
        String requestUrl = "https://api.twitter.com/1.1/users/show.json?user_id=" + userId;

        // подключаемся к серверу
        URL url = new URL(requestUrl);
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
        connection.connect();

        return null;
    }
}

 

Важно, что эти методы могут выбрасывать исключения. Поэтому необходимо либо обернуть этот код в блок try, catch, либо добавить в сигнатуру метода throws IOException, чтобы избежать ошибок компиляции. Тогда код, который будет вызывать этот метод обязан будет обработать исключения. Мы выбрали второй вариант, чтобы клиентский код сам обрабатывал ошибки.

Подробнее про исключения здесь.

Добавление информации об авторизации пользователя

Помните, что метод не работает без информации об авторизации? Мы должны добавить эту информацию в наш запрос во время подключения. Помним, что библиотека tiwtter-kit хранит данные о пользователе, поэтому в методе getAuthHeader() мы просто используем её. Можете просто скопировать этот метод и его использование. На данном этапе обучения эта информация не является важной. После добавления метода и его использования код выглядит так:

 

HtppClient.java

 1
 2
 3
 4
 5
 6
 7
 8
 9
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
36
37
38
package colibri.dev.com.colibritweet.network;

import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;

import com.twitter.sdk.android.core.TwitterAuthConfig;
import com.twitter.sdk.android.core.TwitterCore;
import com.twitter.sdk.android.core.TwitterSession;
import com.twitter.sdk.android.core.internal.oauth.OAuth1aHeaders;

public class HttpClient {
    private static final String HEADER_AUTHORIZATION = "Authorization";
    private static final String GET = "GET";

    public String readUserInfo(long userId) throws IOException {
        String requestUrl = "https://api.twitter.com/1.1/users/show.json?user_id=" + userId;

        URL url = new URL(requestUrl);
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();

        // add auth header to request
        String authHeader = getAuthHeader(requestUrl);
        connection.setRequestProperty(HEADER_AUTHORIZATION, authHeader);

        connection.connect();

        return null;
    }

    private String getAuthHeader(String url) {
        TwitterAuthConfig authConfig = TwitterCore.getInstance().getAuthConfig();
        TwitterSession session = TwitterCore.getInstance().getSessionManager().getActiveSession();

        return new OAuth1aHeaders().getAuthorizationHeader(authConfig,
                session.getAuthToken(), null, GET, url, null);
    }
}

 

Видим, что добавился метод getAuthHeader(String url), который отдаёт нам информацию об авторизации, которую необходимо указать при запросе.

В методе readUserInfo() мы используем эту информацию с помощью connection.setRequestProperty(HEADER_AUTHORIZATION, authHeader). На этом этапе достаточно понимать, что данный код добавляет в запрос информацию об авторизации пользователя, которая необходима для работы метода.

Считывание ответа от сервера

Алгоритм считывания ответа такой:

  • Смотрим статус подключения
  • Получаем входной поток данных от нашего объекта connection. Если статус отличается от статуса 200, то мы считываем поток ошибок, иначе поток корректного ответа.
  • После этого нам необходимо преобразовать поток данных типа InputStream к привычному нам формату String. Это мы сделаем используя функцию convertStreamToString(InputStream stream).

Так всё это выглядит в java коде:

 

HtppClient.java

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
public class HttpClient {

    public String readUserInfo(long userId) throws IOException {
        // остальной код выше не изменился
        InputStream in;
        int status = connection.getResponseCode();
        if (status != HttpURLConnection.HTTP_OK) {
            in = connection.getErrorStream();
        } else {
            in = connection.getInputStream();
        }

        String response = convertStreamToString(in);

        return response;
    }

    private String convertStreamToString(InputStream stream) throws IOException {

        BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
        StringBuilder sb = new StringBuilder();

        String line;
        while ((line = reader.readLine()) != null) {
            sb.append(line).append("\n");
        }
        stream.close();

        return sb.toString();
    }

    // остальной код ниже не изменился
}

 

Суть работы метода convertStreamToString(InputStream stream) заключается в том, что он пробегается по каждой строке потока данных InputStream и записывает их в наш строку, добавляя переносы строк. На выходе получим обыкновенную строку типа String.

Вот и всё, теперь мы реализовали с вами наш первый HTTP метод.

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

Использование в UserInfoActivity

Давайте теперь выведем в log ответ метода. Напомним, что запросы в сеть являются тяжёлой операцией, поэтому нам нужно делать всю эту работу не в UI потоке. Для этого мы будем использовать класс AsyncTask. Пополнить или освежить свои знания можно посмотрев этот урок.

Давайте добавим объект HttpClient в UserInfoActivity и немного изменим метод loadUserInfo(). Помним, что в прошлом уроке мы написали код, который достаёт из Intent id пользователя, переданного с экрана AuthActivity или SearchUsersActivity. Давайте будем передавать этот id в качестве параметра метода loadUserInfo().

 

UserInfoActivity.java

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
public class UserInfoActivity extends AppCompatActivity {
    // остальной код выше не изменился
    private HttpClient httpClient;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // остальной код выше не изменился

        httpClient = new HttpClient();
        loadUserInfo(userId);
        loadTweets();
    }

    private void loadUserInfo(Long userId) {
        new AsyncTask<Void, Void, String>() {
            @Override
            protected String doInBackground(Void... voids) {
                try {
                    return httpClient.readUserInfo(userId);
                } catch (IOException e) {
                    e.printStackTrace();
                    return null;
                }
            }

            @Override
            protected void onPostExecute(String response) {
                Log.d("HttpTest", response);
            }
        }.execute();
    }
}

 

AndroidStudio выделяет код Asynctask, сообщая о проблеме утечки памяти. Пока просто игнорируем это, а в дальнейшем исправим это замечание. Мы можем нажать сочетание клавиш Alt + Enter и выбрать пункт Suppress: Add @SuppressLint("StaticFieldLeak") annotation. Этим мы говорим, чтобы анализатор кода игнорировал это замечание. После этого над нашим методом появится аннотация @SuppressLint("StaticFieldLeak").

 

AsynctaskSuppress.png

 

Запустим наше приложение и посмотрим, что же мы получили в логах.

 

LogResponse.png

 

Обязательно в имени фильтра введите HttpTest, чтобы увидеть только тот лог, который мы выводим внутри AsyncTask. Видим, что нам пришёл ответ. Давайте скопируем его и посмотрим содержимое. Повторяем все действия, которые уже проделывали в блоке [Копирование, форматирование ответа от сервера]. После чего видим, что наш ответ выглядит так:

 

  1
  2
  3
  4
  5
  6
  7
  8
  9
 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
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
{
    "id": 929257819349700600,
    "id_str": "929257819349700608",
    "name": "Devcolibri",
    "screen_name": "devcolibri",
    "location": "Republic of Belarus",
    "profile_location": {
        "id": "333a5811d6b0c1cb",
        "url": "https://api.twitter.com/1.1/geo/id/333a5811d6b0c1cb.json",
        "place_type": "unknown",
        "name": "Republic of Belarus",
        "full_name": "Republic of Belarus",
        "country_code": "",
        "country": "",
        "contained_within": [],
        "bounding_box": null,
        "attributes": {}
    },
    "description": "Образовательный IT-портал. Android, Java, Kotlin.",
    "url": "https://t.co/WpJK4WyLh8",
    "entities": {
        "url": {
            "urls": [
                {
                    "url": "https://t.co/WpJK4WyLh8",
                    "expanded_url": "https://devcolibri.com/",
                    "display_url": "devcolibri.com",
                    "indices": [
                        0,
                        23
                    ]
                }
            ]
        },
        "description": {
            "urls": []
        }
    },
    "protected": false,
    "followers_count": 7,
    "friends_count": 4,
    "listed_count": 0,
    "created_at": "Sat Nov 11 08:01:43 +0000 2017",
    "favourites_count": 0,
    "utc_offset": null,
    "time_zone": null,
    "geo_enabled": false,
    "verified": false,
    "statuses_count": 5,
    "lang": "en",
    "status": {
        "created_at": "Mon Nov 27 08:03:40 +0000 2017",
        "id": 935056513667825700,
        "id_str": "935056513667825665",
        "text": "Сегодня поговорим о RecyclerView и о том, почему нужно использовать именно его.\n\nhttps://t.co/ICTsW7KLbf… https://t.co/XEhL7w4YHX",
        "truncated": true,
        "entities": {
            "hashtags": [],
            "symbols": [],
            "user_mentions": [],
            "urls": [
                {
                    "url": "https://t.co/ICTsW7KLbf",
                    "expanded_url": "https://devcolibri.com/%D0%BA%D0%B0%D0%BA-%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D0%B0%D1%82%D1%8C-%D1%81-recyclerview/",
                    "display_url": "devcolibri.com/%D0%BA%D0%B0%D…",
                    "indices": [
                        81,
                        104
                    ]
                },
                {
                    "url": "https://t.co/XEhL7w4YHX",
                    "expanded_url": "https://twitter.com/i/web/status/935056513667825665",
                    "display_url": "twitter.com/i/web/status/9…",
                    "indices": [
                        106,
                        129
                    ]
                }
            ]
        },
        "source": "<a href=\"http://twitter.com\" rel=\"nofollow\">Twitter Web Client</a>",
        "in_reply_to_status_id": null,
        "in_reply_to_status_id_str": null,
        "in_reply_to_user_id": null,
        "in_reply_to_user_id_str": null,
        "in_reply_to_screen_name": null,
        "geo": null,
        "coordinates": null,
        "place": null,
        "contributors": null,
        "is_quote_status": false,
        "retweet_count": 0,
        "favorite_count": 0,
        "favorited": false,
        "retweeted": false,
        "possibly_sensitive": false,
        "lang": "ru"
    },
    "contributors_enabled": false,
    "is_translator": false,
    "is_translation_enabled": false,
    "profile_background_color": "000000",
    "profile_background_image_url": "http://abs.twimg.com/images/themes/theme1/bg.png",
    "profile_background_image_url_https": "https://abs.twimg.com/images/themes/theme1/bg.png",
    "profile_background_tile": false,
    "profile_image_url": "http://pbs.twimg.com/profile_images/929258919402377216/JDAtj1H__normal.jpg",
    "profile_image_url_https": "https://pbs.twimg.com/profile_images/929258919402377216/JDAtj1H__normal.jpg",
    "profile_link_color": "2F3F4C",
    "profile_sidebar_border_color": "000000",
    "profile_sidebar_fill_color": "000000",
    "profile_text_color": "000000",
    "profile_use_background_image": false,
    "has_extended_profile": true,
    "default_profile": false,
    "default_profile_image": false,
    "following": false,
    "follow_request_sent": false,
    "notifications": false,
    "translator_type": "none",
    "suspended": false,
    "needs_phone_verification": false
}

 

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

Полный листинг кода:

 

HttpClient.java

 1
 2
 3
 4
 5
 6
 7
 8
 9
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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
package colibri.dev.com.colibritweet.network;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;

import com.twitter.sdk.android.core.TwitterAuthConfig;
import com.twitter.sdk.android.core.TwitterCore;
import com.twitter.sdk.android.core.TwitterSession;
import com.twitter.sdk.android.core.internal.oauth.OAuth1aHeaders;

public class HttpClient {
    private static final String HEADER_AUTHORIZATION = "Authorization";
    private static final String GET = "GET";

    public String readUserInfo(long userId) throws IOException {
        String requestUrl = "https://api.twitter.com/1.1/users/show.json?user_id=" + userId;

        URL url = new URL(requestUrl);
        HttpURLConnection connection = (HttpURLConnection) url.openConnection();

        // add auth header to request
        String authHeader = getAuthHeader(requestUrl);
        connection.setRequestProperty(HEADER_AUTHORIZATION, authHeader);

        connection.connect();

        InputStream in;
        int status = connection.getResponseCode();
        if (status != HttpURLConnection.HTTP_OK) {
            in = connection.getErrorStream();
        } else {
            in = connection.getInputStream();
        }

        String response = convertStreamToString(in);

        return response;
    }

    private String convertStreamToString(InputStream stream) throws IOException {

        BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
        StringBuilder sb = new StringBuilder();

        String line;
        while ((line = reader.readLine()) != null) {
            sb.append(line).append("\n");
        }
        stream.close();

        return sb.toString();
    }

    private String getAuthHeader(String url) {
        TwitterAuthConfig authConfig = TwitterCore.getInstance().getAuthConfig();
        TwitterSession session = TwitterCore.getInstance().getSessionManager().getActiveSession();

        return new OAuth1aHeaders().getAuthorizationHeader(authConfig,
                session.getAuthToken(), null, GET, url, null);
    }
}

 

UserInfoActivity.java

  1
  2
  3
  4
  5
  6
  7
  8
  9
 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
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
package colibri.dev.com.colibritweet.activity;

import java.io.IOException;
import java.util.Arrays;
import java.util.Collection;

import android.annotation.SuppressLint;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;

import com.squareup.picasso.Picasso;

import colibri.dev.com.colibritweet.R;
import colibri.dev.com.colibritweet.adapter.TweetAdapter;
import colibri.dev.com.colibritweet.network.HttpClient;
import colibri.dev.com.colibritweet.pojo.Tweet;
import colibri.dev.com.colibritweet.pojo.User;

public class UserInfoActivity extends AppCompatActivity {
    private ImageView userImageView;
    private TextView nameTextView;
    private TextView nickTextView;
    private TextView descriptionTextView;
    private TextView locationTextView;
    private TextView followingCountTextView;
    private TextView followersCountTextView;

    private RecyclerView tweetsRecyclerView;
    private TweetAdapter tweetAdapter;
    private Toolbar toolbar;

    private HttpClient httpClient;

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

        // остальной код выше не изменился
        long userId = getIntent().getLongExtra(AuthActivity.USER_ID, -1);

        userImageView = findViewById(R.id.user_image_view);
        nameTextView = findViewById(R.id.user_name_text_view);
        nickTextView = findViewById(R.id.user_nick_text_view);
        descriptionTextView = findViewById(R.id.user_description_text_view);
        locationTextView = findViewById(R.id.user_location_text_view);
        followingCountTextView = findViewById(R.id.following_count_text_view);
        followersCountTextView = findViewById(R.id.followers_count_text_view);

        toolbar = findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        initRecyclerView();

        httpClient = new HttpClient();
        loadUserInfo(userId);
        loadTweets();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.user_info_menu, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        if(item.getItemId() == R.id.action_search) {
            Intent intent = new Intent(this, SearchUsersActivity.class);
            startActivity(intent);
        }
        return true;
    }

    private void loadTweets() {
        Collection<Tweet> tweets = getTweets();
        tweetAdapter.setItems(tweets);
    }

    private Collection<Tweet> getTweets() {
        return Arrays.asList(
                new Tweet(getUser(), 1L, "Thu Dec 13 07:31:08 +0000 2017", "Очень длинное описание твита 1",
                        4L, 4L, "https://www.w3schools.com/w3css/img_fjords.jpg"),

                new Tweet(getUser(), 2L, "Thu Dec 12 07:31:08 +0000 2017", "Очень длинное описание твита 2",
                        5L, 5L, "https://www.w3schools.com/w3images/lights.jpg"),

                new Tweet(getUser(), 3L, "Thu Dec 11 07:31:08 +0000 2017", "Очень длинное описание твита 3",
                        6L, 6L, "https://www.w3schools.com/css/img_mountains.jpg")
        );
    }

    private void initRecyclerView() {
        tweetsRecyclerView = findViewById(R.id.tweets_recycler_view);
        tweetsRecyclerView.setLayoutManager(new LinearLayoutManager(this));
        tweetAdapter = new TweetAdapter();
        tweetsRecyclerView.setAdapter(tweetAdapter);
    }

    @SuppressLint("StaticFieldLeak")
    private void loadUserInfo(final Long userId) {
        new AsyncTask<Void, Void, String>() {
            @Override
            protected String doInBackground(Void... voids) {
                try {
                    return httpClient.readUserInfo(userId);
                } catch (IOException e) {
                    e.printStackTrace();
                    return null;
                }
            }

            @Override
            protected void onPostExecute(String response) {
                Log.d("HttpTest", response);
            }
        }.execute();
    }

    private void displayUserInfo(User user) {
        Picasso.with(this).load(user.getImageUrl()).into(userImageView);
        nameTextView.setText(user.getName());
        nickTextView.setText(user.getNick());
        descriptionTextView.setText(user.getDescription());
        locationTextView.setText(user.getLocation());

        String followingCount = String.valueOf(user.getFollowingCount());
        followingCountTextView.setText(followingCount);

        String followersCount = String.valueOf(user.getFollowersCount());
        followersCountTextView.setText(followersCount);
        getSupportActionBar().setTitle(user.getName());
    }

    private User getUser() {
        return new User(
                1L,
                "http://i.imgur.com/DvpvklR.png",
                "DevColibri",
                "devcolibri",
                "Sample description",
                "USA",
                42,
                42
        );
    }
}

 

Подведём итоги:

  • HTTP протокол часто используется для общения клиент-серверных приложений.
  • Удобно вначале изучить формат API, используя веб-консоль, чтобы понять, как именно работает API.
  • Реализация HTTP в Android довольно низкоуровневая. Но стоит знать, что реализовать HTTP можно и не используя сторонних библиотек.
УВИДЕТЬ ВСЕ Добавить заметку
Вы
Добавить ваш комментарий
 

Сайт использует cookie-файлы для того, чтобы вам было удобнее им пользоваться. Для продолжения работы с сайтом, вам необходимо принять использование cookie-файлов.

Я ознакомлен(а)