Создание View объектов в java коде. Связывание их с xml объектами
Первое, что нам надо сделать сегодня – это создать все наши View-компоненты в java коде и связать их с элементами в layout файле. Для этого в Activity нам необходимо для каждого View-компонента вызвать метод findViewById(int id) (рус. найти элемент по идентификатору), на вход которому необходимо передать идентификатор (id) элемента, который прописан нами в xml-файле. Выглядит это так:
Зачем нам это необходимо? На этапе создания layout файла мы можем не обращаться к java коду вообще. Но в обычном приложении все данные поступают в layout динамически из java кода. Поэтому давайте создадим метод displayUserInfo() и там просто присвоим нашим View какое-то временное содержимое. Этот методм нам нужно будет вызывать всякий раз, когда мы захотим обновить информацию на нашем экране:
Мы используем обычный метод setText(), чтобы установить какой-то текст в наши TextView. Этот код уже больше похож на реальный, потому что именно так мы и будем устанавливать данные в наши View, когда получим ответ от сервера.
Добавление POJO объекта User.
Простые объекты в java называют POJO. POJO (англ. Plain Old Java Object) — «старый добрый Java-объект», простой Java-объект, не унаследованный от какого-то специфического объекта и не реализующий никаких служебных интерфейсов сверх тех, которые нужны для бизнес-модели.
Объекты нужны для того, чтобы хранить информацию в удобном для нас виде. Т.е. когда у себя в коде мы представляем данные в виде объектов реального мира. Есть пользователь User, у которого есть имя (поле name) и т.д.
Единственное, что нам осталось сделать – это добавить объект, который будет представлять все данные, которыми обладает пользователь. В нашем случае нам нужны следующие поля:
Идентификатор пользователя id
Ссылка на фотографию imageUrl
Имя пользователя name
Ник пользователя nick
Описание пользователя description
Местоположение пользователя location
Количество тех, кого читает пользователь followingCount
Количество тех, кто читает пользователя followersCount
Давайте создадим новый файл User.java. Только давайте перед этим создадим новый пакет, где будем хранить все сущности нашего приложения. Для этого нажмите правой кнопкой по пакету (папке) colibri.dev.com.colibritweet и выберите New -> Package:
Назовём наш пакет pojo:
Затем создадим новый класс. Для этого нажмите правой кнопкой по пакету pojo и выберете New -> JavaClass. Введите имя User:
Видим, что у нас создался класс и мы можем добавлять в него свой код:
Отлично, давайте добавим поля, которые мы перечислили:
По умолчанию в сущностях используем модификатор доступа private, для того, чтобы не нарушать инкапсуляцию класса, чтобы внешний код не имел прямого доступа к значению этих полей. Т.е. инкапсуляция – это просто приём сокрытия данных от внешнего вмешательства. Никто кроме класса User не получит доступ к его полям, если только в классе не будут объявлены соответствующие механизмы (например, конструктор, setter-методы, getter-методы).
Поэтому, чтобы установить значения полям, мы создадим конструктор.
Конструктор мы можем создавать либо вручную, либо использовать функции AndroidStudio, чтобы она сделала эту рутинную работу за нас. Для этого надо зажать клавиши Alt + Insert, выбрать из контекстного меню Constructor:
После этого необходимо выбрать поля, которые мы хотим получать в конструкторе. В нашем случае – это все поля, поэтому выбираем все:
В появившемся окне нажимаем OK и видим, что конструктор сгенерировался автоматически.
Мы можем работать с таким классом, но для POJO классов есть ключевое правило: всегда переопределять методы equals() и hashcode(). Если вы не знаете, зачем это нужно, то прервитесь и изучите эту статью.
Эти методы мы тоже сгенерируем автоматически. Для этого снова зажимаем клавиши Alt + Insert, выбираем equals() and hashcode(). После этого перед вами появится окно такого вида:
Здесь мы можем выбрать какой-то кастомный template для генерации методов, но пока будем пользоваться Intellij Default.
Нажимаем Next. После этого видим форму, в которой надо выбрать поля, которые будут включены в метод equals(). Выбираем все поля и нажимаем Next:
После этого видим форму, в которой надо выбрать поля, которые будут включены в метод hashcode(). Снова выбираем все поля и нажимаем Next:
В следующей форме нужно отметить, какие поля у нас всегда будут not null. Это необходимо для того, чтобы во время выполнения методов equals() и hashcode() приложение не сломалось с null pointer exception. В нашем случае у пользователя обязательно должны быть поля id, name, nick. Т.к. поле id является примитивом (типом long), то оно не может быть null не при каких обстоятельствах. Поэтому мы выбираем поля name, nick:
Таким образом, у нас сгенерировались эти два метода:
User.java
publicclassUser {
// Остальной код выше не изменился@Overridepublicbooleanequals(Objecto) {
if (this== o) returntrue;
if (o ==null|| getClass() != o.getClass()) returnfalse;
User user = (User) o;
if (id != user.id) returnfalse;
if (followingCount != user.followingCount) returnfalse;
if (followersCount != user.followersCount) returnfalse;
if (imageUrl !=null?!imageUrl.equals(user.imageUrl) : user.imageUrl !=null)
returnfalse;
if (!name.equals(user.name)) returnfalse;
if (!nick.equals(user.nick)) returnfalse;
if (description !=null?!description.equals(user.description) : user.description !=null) {
returnfalse;
}
return location !=null? location.equals(user.location) : user.location ==null;
}
@OverridepublicinthashCode() {
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;
}
}
Если вы не переопределите эти два методы, то объекты будут сравниваться по ссылке, иначе по тому алгоритму, который описан в этих методах.
Использование POJOUser в UserInfoActivity
Теперь давайте добавим объект User в нашу Activity. Это необходимо, потому что от сервера мы получим именно такой объект. Т.е. на самом деле процесс получения данных пользователя делится на два действия:
Получение данных(объекта User) от источника данных (сервер, база данных, или заглушка для тестов).
Отображение данных.
Давайте создадим метод getUser(), в котором пока будем возвращать тестовый объект. В будущем мы заменим этот метод на взаимодействие с реальным сервером.
UserInfoActivity.java
publicclassUserInfoActivityextendsAppCompatActivity {
// Остальной код выше не изменилсяprivateUsergetUser() {
returnnewUser(
1L,
"http://i.imgur.com/DvpvklR.png",
"DevColibri",
"devcolibri",
"Sample description",
"USA",
42,
42
);
}
}
Видим, что в этом методе мы просто возвращаем в этом объекте все те же самые значения, которые мы использовали до этого.
Также нам надо немного изменить метод отображения данных пользователя. Надо добавить объект User как входной параметр и отображать данные из его полей:
UserInfoActivity.java
publicclassUserInfoActivityextendsAppCompatActivity {
// Остальной код выше не изменилсяprivatevoiddisplayUserInfo(Useruser) {
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).
Запустим приложение и увидим, что все поля объекта успешно отобразились:
Подведём итоги:
При реальной работе приложения данные всегда приходят из java кода. Поэтому необходимо объявлять наши View в java коде и заполнять их информацией из реальных объектов.
Для удобного хранения данных используют POJO объекты. Они повышают уровень абстракции и позволяют хранить данные в виде, приближенном к реальному миру.
Сайт использует cookie-файлы для того, чтобы вам было удобнее им пользоваться. Для
продолжения работы с сайтом, вам необходимо принять использование cookie-файлов.
Код начала урока:
gitzip
Структура урока:
Видео версия урока
Создание View объектов в java коде. Связывание их с xml объектами
Первое, что нам надо сделать сегодня – это создать все наши
View
-компоненты вjava
коде и связать их с элементами вlayout
файле. Для этого вActivity
нам необходимо для каждогоView
-компонента вызвать методfindViewById(int id)
(рус. найти элемент по идентификатору), на вход которому необходимо передать идентификатор (id) элемента, который прописан нами вxml
-файле. Выглядит это так:UserInfoActivity.java
Зачем нам это необходимо? На этапе создания
layout
файла мы можем не обращаться кjava
коду вообще. Но в обычном приложении все данные поступают вlayout
динамически изjava
кода. Поэтому давайте создадим методdisplayUserInfo()
и там просто присвоим нашимView
какое-то временное содержимое. Этот методм нам нужно будет вызывать всякий раз, когда мы захотим обновить информацию на нашем экране:UserInfoActivity.java
Мы используем обычный метод
setText()
, чтобы установить какой-то текст в нашиTextView
. Этот код уже больше похож на реальный, потому что именно так мы и будем устанавливать данные в нашиView
, когда получим ответ от сервера.Добавление POJO объекта User.
Простые объекты в
java
называютPOJO
. POJO (англ. Plain Old Java Object) — «старый добрый Java-объект», простой Java-объект, не унаследованный от какого-то специфического объекта и не реализующий никаких служебных интерфейсов сверх тех, которые нужны для бизнес-модели.Объекты нужны для того, чтобы хранить информацию в удобном для нас виде. Т.е. когда у себя в коде мы представляем данные в виде объектов реального мира. Есть пользователь
User
, у которого есть имя (полеname
) и т.д.Единственное, что нам осталось сделать – это добавить объект, который будет представлять все данные, которыми обладает пользователь. В нашем случае нам нужны следующие поля:
id
imageUrl
name
nick
description
location
followingCount
followersCount
Давайте создадим новый файл
User.java
. Только давайте перед этим создадим новый пакет, где будем хранить все сущности нашего приложения. Для этого нажмите правой кнопкой по пакету (папке)colibri.dev.com.colibritweet
и выберитеNew -> Package
:Назовём наш пакет
pojo
:Затем создадим новый класс. Для этого нажмите правой кнопкой по пакету
pojo
и выберетеNew -> JavaClass
. Введите имяUser
:Видим, что у нас создался класс и мы можем добавлять в него свой код:
Отлично, давайте добавим поля, которые мы перечислили:
User.java
По умолчанию в сущностях используем модификатор доступа
private
, для того, чтобы не нарушать инкапсуляцию класса, чтобы внешний код не имел прямого доступа к значению этих полей. Т.е. инкапсуляция – это просто приём сокрытия данных от внешнего вмешательства. Никто кроме классаUser
не получит доступ к его полям, если только в классе не будут объявлены соответствующие механизмы (например, конструктор,setter
-методы,getter
-методы).Поэтому, чтобы установить значения полям, мы создадим конструктор.
Конструктор мы можем создавать либо вручную, либо использовать функции
AndroidStudio
, чтобы она сделала эту рутинную работу за нас. Для этого надо зажать клавишиAlt + Insert
, выбрать из контекстного менюConstructor
:После этого необходимо выбрать поля, которые мы хотим получать в конструкторе. В нашем случае – это все поля, поэтому выбираем все:
В появившемся окне нажимаем
OK
и видим, что конструктор сгенерировался автоматически.User.java
Также (т.к. поля у нас
private
) нам необходимо создатьgetter
методы для всех полей. Давайте тоже сделаем это автоматически.По аналогии с генерацией конструктора:
Alt + Insert
,Getter
.OK
.Наш класс теперь выглядит так:
User.java
Мы можем работать с таким классом, но для
POJO
классов есть ключевое правило: всегда переопределять методыequals() и hashcode()
. Если вы не знаете, зачем это нужно, то прервитесь и изучите эту статью.Эти методы мы тоже сгенерируем автоматически. Для этого снова зажимаем клавиши
Alt + Insert
, выбираемequals() and hashcode()
. После этого перед вами появится окно такого вида:Здесь мы можем выбрать какой-то кастомный
template
для генерации методов, но пока будем пользоватьсяIntellij Default
.Нажимаем
Next
. После этого видим форму, в которой надо выбрать поля, которые будут включены в методequals()
. Выбираем все поля и нажимаемNext
:После этого видим форму, в которой надо выбрать поля, которые будут включены в метод
hashcode()
. Снова выбираем все поля и нажимаемNext
:В следующей форме нужно отметить, какие поля у нас всегда будут
not null
. Это необходимо для того, чтобы во время выполнения методовequals()
иhashcode()
приложение не сломалось сnull pointer exception
. В нашем случае у пользователя обязательно должны быть поляid
,name
,nick
. Т.к. полеid
является примитивом (типомlong
), то оно не может бытьnull
не при каких обстоятельствах. Поэтому мы выбираем поляname
,nick
:Таким образом, у нас сгенерировались эти два метода:
User.java
Если вы не переопределите эти два методы, то объекты будут сравниваться по ссылке, иначе по тому алгоритму, который описан в этих методах.
Использование POJO User в UserInfoActivity
Теперь давайте добавим объект
User
в нашуActivity
. Это необходимо, потому что от сервера мы получим именно такой объект. Т.е. на самом деле процесс получения данных пользователя делится на два действия:User
) от источника данных (сервер, база данных, или заглушка для тестов).Давайте создадим метод
getUser()
, в котором пока будем возвращать тестовый объект. В будущем мы заменим этот метод на взаимодействие с реальным сервером.UserInfoActivity.java
Видим, что в этом методе мы просто возвращаем в этом объекте все те же самые значения, которые мы использовали до этого.
Также нам надо немного изменить метод отображения данных пользователя. Надо добавить объект
User
как входной параметр и отображать данные из его полей:UserInfoActivity.java
Здесь практически ничего не изменилось. Единственное, что поля
followingCount
иfollowersCount
имеют типint
, а методsetText()
принимает толькоString
входным параметром. Поэтому нам нужно сделать явное приведение к типуString
.Добавим ещё один метод
loadUserInfo()
, который будет вызывать методgetUser()
и передавать его результат в методdisplayUserInfo(user)
.Итоговый код нашей
UserInfoActivity
:UserInfoActivity.java
Запустим приложение и увидим, что все поля объекта успешно отобразились:
Подведём итоги:
java
кода. Поэтому необходимо объявлять нашиView
вjava
коде и заполнять их информацией из реальных объектов.POJO
объекты. Они повышают уровень абстракции и позволяют хранить данные в виде, приближенном к реальному миру.Полезные материалы:
Полный листинг изменений кода:
Code diff