В этом посте описывается одна из самых интересных функций в Android, недавно представленная и все еще в бета-версии: Android Data Binding . Используя привязку данных, вы создаете связь между уровнем представления (пользовательским интерфейсом приложения) и базовой моделью данных, которая содержит информацию, которую вы хотите показать . Содержимое виджетов пользовательского интерфейса, такое как TextView, EditText и т. Д., Каким-то образом связано с данными, хранящимися в классе Java. Каждый раз, когда данные изменяют связанный с ним виджет пользовательского интерфейса, он обновляется , поэтому вам больше не нужно беспокоиться об обновлении пользовательского интерфейса самостоятельно. Если приложение не использует привязку данных Android, необходимо найти представление и обновить содержимое.
Настройка привязки данных Android
Как уже говорилось ранее, эта функция все еще находится в бета-версии, поэтому для начала давайте установим правильные зависимости в build.gradle верхнего уровня:
1
2
3
4
|
dependencies { classpath "com.android.tools.build:gradle:1.3.0" classpath "com.android.databinding:dataBinder:1.+" } |
Кстати, убедитесь, что вы скачали Gradle 2.4 . Теперь зависимости готовы, и пришло время изменить build.gradle в приложении:
1
|
apply plugin: 'com.android.databinding' |
Как использовать привязку данных Android
Теперь, когда среда готова, можно кодировать наше приложение для Android . Например, мы создадим простое приложение погоды, которое отображает температуру и другую информацию, в данном случае для отображения данных приложение будет использовать привязку данных.
Прежде всего, мы создаем макет, который будет очень простым, но он будет содержать некоторые важные вещи, которые мы должны заметить:
001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
071
072
073
074
075
076
077
078
079
080
081
082
083
084
085
086
087
088
089
090
091
092
093
094
095
096
097
098
099
100
101
|
< data > < variable name = "data" type = "survivingwithandroid.com.androiddatabinding.model.Data" /> </ data > < RelativeLayout 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" > < android.support.v7.widget.Toolbar android:id = "@+id/toolbar" android:layout_height = "wrap_content" android:layout_width = "match_parent" android:background = "@color/primary" android:elevation = "4dp" app:theme = "@style/ThemeOverlay.AppCompat.Dark" /> < TextView android:layout_width = "wrap_content" android:layout_height = "wrap_content" android:layout_centerHorizontal = "true" android:layout_marginTop = "10dp" android:layout_below = "@id/toolbar" android:text = "@{data.city}" android:textSize = "18dp" android:id = "@+id/weather_icon" /> < ImageView android:layout_width = "60dp" android:layout_height = "60dp" android:layout_centerInParent = "true" android:src = "@{data.icon}" /> < TextView android:layout_width = "wrap_content" android:layout_height = "wrap_content" android:layout_centerHorizontal = "true" android:text = "@{data.descr}" android:layout_marginTop = "10dp" android:layout_below = "@id/weather_icon" /> < GridLayout android:layout_width = "wrap_content" android:layout_height = "wrap_content" android:layout_marginLeft = "15dp" android:layout_marginRight = "15dp" android:layout_alignParentBottom = "true" android:layout_marginBottom = "15dp" android:rowCount = "1" android:columnCount = "4" android:layout_centerHorizontal = "true" android:layout_centerVertical = "true" > < TextView android:id = "@+id/temp" android:layout_width = "60dp" android:layout_height = "60dp" android:text = "@{data.temp}" android:layout_row = "0" android:layout_column = "0" android:layout_gravity = "center" /> < TextView android:id = "@+id/press" android:layout_width = "60dp" android:layout_height = "60dp" android:text = "@{data.pressure}" android:layout_row = "0" android:layout_column = "1" android:layout_gravity = "center" /> < TextView android:id = "@+id/hum" android:layout_width = "60dp" android:layout_height = "60dp" android:text = "@{data.humidity}" android:layout_row = "0" android:layout_column = "2" android:layout_gravity = "center" /> < TextView android:id = "@+id/wind" android:layout_width = "60dp" android:layout_height = "60dp" android:text = "@{data.wind}" android:layout_row = "0" android:layout_column = "3" android:layout_gravity = "center" /> </ GridLayout > </ RelativeLayout > </ layout > |
Корнем макета пользовательского интерфейса приложения является макет, а затем объявляется переменная, которую мы хотим использовать в нашем макете (строка 3-5). Важно объявить эти переменные, потому что они будут использоваться в процессе привязки. В строке 4 указывается, что переменные данные — это тип SurviveWandhandroid.com.androiddatabinding.model.Data, который содержит данные, которые мы хотим показать. В другом мире этот класс является POJO, который связан с пользовательским интерфейсом. В виджетах TextView значение каждого поля класса POJO привязано к соответствующему тексту android: text, поэтому значение отображается автоматически.
Привязка переменной к объекту
Теперь макет готов и можно привязать поле класса к виджету пользовательского интерфейса. В методе onCreate мы получаем ссылку на текущий макет Activity другим способом по сравнению с обычным способом:
1
2
3
4
5
6
7
8
|
@Override protected void onCreate(Bundle savedInstanceState) { super .onCreate(savedInstanceState); //setContentView(R.layout.activity_main); binding = DataBindingUtil.setContentView( this , R.layout.activity_main); binding.setData(data); .... } |
где данные определены как:
1
|
private Data data = new Data(); //survivingwithandroid.com.androiddatabinding.model.Data; |
Обратите внимание, что в строке 5 мы устанавливаем макет активности, а затем разрешаем переменную, используемую в макете. Если мы запустим приложение таким образом, мы заметим, что данные пользовательского интерфейса обновляются только один раз в начале, когда нижележащее поле класса, связанное с пользовательским интерфейсом, изменяет пользовательский интерфейс, не отражает изменения. Это происходит потому, что необходимо создать прослушиватель между пользовательским интерфейсом и полем данных.
Первым шагом является то, что наш класс данных POJO расширяет BaseObservable:
1
2
3
|
public class Data extends BaseObservable { .... } |
Теперь необходимо привязать одно поле класса к пользовательскому интерфейсу, например, для поля температуры:
01
02
03
04
05
06
07
08
09
10
11
12
13
|
public class Data extends BaseObservable { .. @Bindable public String getTemp() { return temp; } public void setTemp(String temp) { this .temp = temp; notifyPropertyChanged(BR.temp); } .. } |
Аннотация @Bindable
используется для создания ссылки между пользовательским интерфейсом и полем, а notifyPropertyChanged
информирует слушателя об изменении подстилающего поля и необходимости обновления представления. Выполнение примера с использованием привязки данных Android приводит к следующему:
Вывод
Как мы уже заметили, привязка данных Android — очень интересная и мощная функция, которая может значительно упростить создание приложений. В любом случае, он все еще находится в бета-версии, и есть некоторые небольшие проблемы: например, даже если я попытался обновить ImageView таким же способом и установить идентификатор ресурса, он не работал. Это моя ошибка? !!
Ссылка: | Учебное пособие по привязке данных Android от нашего партнера JCG Франческо Аццолы в блоге Surviving с Android . |