Урок 8. Создание POJO объекта User. Работа с View из java кода – Devcolibri – Android для начинающих

Урок 8. Создание POJO объекта User. Работа с View из java кода

Создание View объектов в java коде. Связывание их с xml объектами

Первое, что нам надо сделать сегодня – это создать все наши View-компоненты в java коде и связать их с элементами в layout файле. Выглядит это так:

 

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
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;

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

        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);
    }
}

 

Зачем нам это надо? На этапе создания layout файла мы можем не обращаться к java коду вообще. Но в обычном приложении все данные поступают в layout динамически из java кода. Поэтому давайте создадим метод displayUserInfo() и там просто присвоим нашим View какое-то временное содержимое.

 

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
package colibri.dev.com.colibritweet;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.ImageView;
import android.widget.TextView;

import com.squareup.picasso.Picasso;

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;

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

        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);

        displayUserInfo();
    }

    private void displayUserInfo() {
        Picasso.with(this).load("http://i.imgur.com/DvpvklR.png").into(userImageView);
        nameTextView.setText("DevColibri");
        nickTextView.setText("@devcolibri");
        descriptionTextView.setText("Sample description");
        locationTextView.setText("USA");
        followingCountTextView.setText("42");
        followersCountTextView.setText("42");
    }
}

 

Мы используем обычный метод setText(), чтобы установить какой-то текст в наши TextView. Этот код уже больше похож на реальный, потому что именно так мы и будем устанавливать данные в наши View, когда получим ответ от сервера.

Добавление POJO объекта User.

Простые объекты в java называют POJOPOJO (англ. Plain Old Java Object) — «старый добрый Java-объект», простой Java-объект, не унаследованный от какого-то специфического объекта и не реализующий никаких служебных интерфейсов сверх тех, которые нужны для бизнес-модели.

Объекты нужны для того, чтобы хранить информацию в удобном для нас виде. Т.е. когда у себя в коде мы представляем данные в виде объектов реального мира. Есть пользователь User, у которого есть имя (поле name) и т.д.

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

  • Идентификатор пользователя id
  • Ссылка на фотографию imageUrl
  • Имя пользователя name
  • Ник пользователя nick
  • Описание пользователя description
  • Местоположение пользователя location
  • Количество тех, кого читает пользователь followingCount
  • Количество тех, кто читает пользователя followersCount

Давайте создадим новый файл User.java. Только давайте перед этим создадим новый пакет, где будем хранить все сущности нашего приложения. Для этого нажмите правой кнопкой по пакету (папке) colibri.dev.com.colibritweet и выберете New -> Package.

 

PojoPackage.png

 

Назовём наш пакет pojo.

 

PojoName.png

 

После этого нам надо создать новый класс. Для этого нажмите правой кнопкой по пакету pojo и выберете New -> JavaClass. Введите имя User.

 

UserClassPopup.png

 

UserClassName.png

 

Видим, что у нас создался класс и мы можем добавлять в него свой код.

 

UserClassCreated.png

 

Отлично, давайте добавим поля, которые мы перечислили.

 

User.java

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
public class User {
    private long id;
    private String imageUrl;
    private String name;
    private String nick;
    private String description;
    private String location;
    private int followingCount;
    private int followersCount;
}

 

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

Конструктор мы можем создавать либо вручную, либо использовать функции AndroidStudio, чтобы она сделала эту рутинную работу за нас. Для этого надо зажать клавиши Alt + Insert, выбрать из контекстного меню Constructor.

 

UserClassConstructorPopup.png

 

После этого надо выбрать поля, которые мы хотим получать в конструкторе. В нашем случае – это все поля, поэтому выбираем все.

 

UserClassConstructorFields.png

 

После этого нажимаем OK и видим, что конструктор сгенерировался автоматически.

 

User.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
public class User {
    private long id;
    private String imageUrl;
    private String name;
    private String nick;
    private String description;
    private String location;
    private int followingCount;
    private int followersCount;

    public User(long id,
                String imageUrl,
                String name,
                String nick,
                String description,
                String location,
                int followingCount,
                int followersCount) {
        this.id = id;
        this.imageUrl = imageUrl;
        this.name = name;
        this.nick = nick;
        this.description = description;
        this.location = location;
        this.followingCount = followingCount;
        this.followersCount = followersCount;
    }

 

Также (т.к. поля у нас private) нам надо создать getter методы для всех полей. Давайте тоже сделаем это автоматически.

По ананлогии с генерацией констурктора:

  • зажимаем клавиши Alt + Insert,
  • выбираем из контекстного меню Getter.
  • выбираем все поля
  • нажимаем OK.

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

 

 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
public class User {
    private long id;
    private String imageUrl;
    private String name;
    private String nick;
    private String description;
    private String location;
    private int followingCount;
    private int followersCount;

    public User(long id,
                String imageUrl,
                String name,
                String nick,
                String description,
                String location,
                int followingCount,
                int followersCount) {
        this.id = id;
        this.imageUrl = imageUrl;
        this.name = name;
        this.nick = nick;
        this.description = description;
        this.location = location;
        this.followingCount = followingCount;
        this.followersCount = followersCount;
    }

    public long getId() {
        return id;
    }

    public String getImageUrl() {
        return imageUrl;
    }

    public String getName() {
        return name;
    }

    public String getNick() {
        return nick;
    }

    public String getDescription() {
        return description;
    }

    public String getLocation() {
        return location;
    }

    public int getFollowingCount() {
        return followingCount;
    }

    public int getFollowersCount() {
        return followersCount;
    }
}

 

Мы можем работать с таким классом, но для POJO классов есть правило большого пальца: всегда переопределять методы equals() и hashcode(). Если кто-то не знает, зачем это надо, то прервитесь и изучите эту статью.

Эти методы мы тоже сгенерируем автоматически. Для этого снова зажимаем клавиши Alt + Insert, выбираем equals() and hashcode(). После этого перед вами появится окно такого вида:

 

UserClassEqualsHashCode.png

 

Здесь мы можем выбрать какой-то кастомный template для генерации методов, но пока будем пользоваться Intellij Default.

Нажимаем Next. После этого видим форму, в которой надо выбрать поля, который будут включены в метод equals(). Выбираем все поля, нажимаем Next

 

UserClassEqualsFields.png

 

После этого видим форму, в которой надо выбрать поля, который будут включены в метод hashcode(). Выбираем все поля, нажимаем Next.

 

UserClassHashcodeFields.png

 

После этого, видим форму, в которой надо отметить, какие поля у нас всегда будут not null. Это надо, чтобы во время выполнения методов equals() и hashcode()приложение не сломалось с null pointer exception. В нашем случае у пользователя обязательно должны быть поля idnamenick. Т.к. поле id является примитивом (типом long), то оно не может быть null не при каких обстоятельствах. Поэтому мы выбираем поля namenick.

 

UserClassEqualsHashcodeNonNull.png

 

После этого видим, что у нас сгенерировались эти два метода.

 

User.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
public class User {
// Отстальной код выше не изменился
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        User user = (User) o;

        if (id != user.id) return false;
        if (followingCount != user.followingCount) return false;
        if (followersCount != user.followersCount) return false;
        if (imageUrl != null ? !imageUrl.equals(user.imageUrl) : user.imageUrl != null)
            return false;
        if (!name.equals(user.name)) return false;
        if (!nick.equals(user.nick)) return false;
        if (description != null ? !description.equals(user.description) : user.description != null) {
            return false;
        }
        return location != null ? location.equals(user.location) : user.location == null;
    }

    @Override
    public int hashCode() {
        int result = (int) (id ^ (id >>> 32));
        result = 31 * result + (imageUrl != null ? imageUrl.hashCode() : 0);
        result = 31 * result + name.hashCode();
        result = 31 * result + nick.hashCode();
        result = 31 * result + (description != null ? description.hashCode() : 0);
        result = 31 * result + (location != null ? location.hashCode() : 0);
        result = 31 * result + followingCount;
        result = 31 * result + followersCount;
        return result;
    }
}

 

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

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

Теперь давайте добавим объект User в нашу Activity. Это надо, потому что от сервера мы получим именно такой объект. Т.е. на самом деле процесс получения данных пользователя делится на два действия:

  • Получение данных(объекта User) от источника данных (сервер, база данных, или заглушка для тестов).
  • Отображение данных.

Давайте создадим метод getUser(), в котором пока будем возвращать тестовый объект. В будущем мы заменим этот метод на взаимодейстие с реальным сервером.

 

UserInfoActivity.java

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
public class UserInfoActivity extends AppCompatActivity {
    // Остальной код выше не изменился
    private User getUser() {
        return new User(
                1L,
                "http://i.imgur.com/DvpvklR.png",
                "DevColibri",
                "devcolibri",
                "Sample description",
                "USA",
                42,
                42
        );
    }
}

 

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

Также нам надо немного изменить метод отображения данных пользователя. Надо добавить объект User как входной параметр и отображать данные из его полей.

 

UserInfoActivity.java

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
public class UserInfoActivity extends AppCompatActivity {
    // Остальной код выше не изменился
    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);
    }
    // Остальной код ниже не изменился
}

 

Здесь практически ничего не изменилось. Единственное, что поля followingCount и followersCount имеют тип int, а метод setText() принимает только String входным параметром. Поэтому нам нужно сделать явное привидение к типу String.

Добавим ещё один метод loadUserInfo(), который будет вызывать метод getUser() и передавать его результат в метод displayUserInfo(user).

Итоговый код нашей UserInfoActivity:

 

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
package colibri.dev.com.colibritweet;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.ImageView;
import android.widget.TextView;

import com.squareup.picasso.Picasso;

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;

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

        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);

        loadUserInfo();
    }

    private void loadUserInfo() {
        User user = getUser();
        displayUserInfo(user);
    }

    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);
    }

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

 

Запустим приложение. Видим, что все поля объекта успешно отобразились.

 

Result.png

 

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

  • При реальной работе приложения данные всегда приходят из java кода. Поэтому необходимо объявлять наши View в java коде и заполнять их информацией из реальных объектов.
  • Для удобного хранения данных используют POJO объекты. Они повышают уровень абстракции и позволяют хранить данные в виде, приближенном к реальному миру.
УВИДЕТЬ ВСЕ Добавить заметку
Вы
Добавить ваш комментарий
 

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

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