Faster Android development with data binding
Android
Data Binding creates a link between UI layer and the underlying data model that
holds the information to display. In normal Android app, it is necessary to
find the view and update the content. Every time data changes the User Interface
widget (TextView, ImageView etc.) bound to it is needs to be update. Lots of
hours were wasted on writing and maintaining trivial and almost useless code
occupying tens or even hundreds of lines in almost all Activity.
The
real power of data binding is when the updating of a value occurs at many
points in an application code. In that situation, the developer doesn’t have to
keep track of all the ways a value can be updated. Using data binding can lead
to faster development times, faster execution times and more readable and
maintained code.
Android
data binding generates binding classes at compile time for layouts.
Getting
Ready
The
Data Binding Library is available for android platforms from Android 2.1 (API 7) and
newer. Add the dataBinding element to your app build.gradle file to enable Data
Binding.
android
{
dataBinding.enabled = true
}
Binding Layout
and Objects
Binding
layout files must be configured slightly differently from default layout files.
All layout files that intend to use data binding techniques must have a layout<>
root tag.
To
bind objects it is required to add data<> tag within the layout
tag, before the UI view root. data<> element can have
multiple variable<> tag within it that describes a property that
can be used within the layout.
Our
sample activity_main.xml layout would be looks like:
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:context="com.androidjavapoint.databindingsample.MainActivity">
<data>
<variable
name="user"
type="com.androidjavapoint.databindingsample.User" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin">
<TextView
android:id="@+id/textFirstName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{user.firstname}" />
<TextView
android:id="@+id/textLastName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{user.lastname}" />
</LinearLayout>
</layout>
User.java
public class User {
/* constructor */
private String firstname;
private String lastname;
/* getters and setters */
}
In
the layout above, you can see that <layout> used as a root tag and
User.java is used as a data object in the <variable> tag inside
<data> tag. Apart from this TextViews have their text set using data
binding “@{}” syntax (@{user.firstname} and @{user.lastname}).
Data Binding
Activity
Now
we have a layout file that is data binding capable. To utilize its data binding
ability we have to load it in a different way. With data binding, a Binding
class is auto generated from your layout file. By default, Binding class is
generated based on the layout file name converted into CamelCase with “Binding”
suffix added to it like activity_main.xml will result in a class called
ActivityMainBinding.
To
associate this generated binding class, need to invoke setContentView of
DataBindingUtil class like.
MainActivity.java
// This was the typical way
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final TextView textFirstName = (TextView)findViewById(R.id.textFirstName);
final TextView textLastName = (TextView)findViewById(R.id.textLastName);
textFirstName.setText("TestFirstName");
textLastName.setText("textLastName");
}
// This was the new way to do using data binding
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
User myUser = new User("TestFirstName", "TestLastName");
binding.setUser(myUser);
}
// This was the typical way
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
final TextView textFirstName = (TextView)findViewById(R.id.textFirstName);
final TextView textLastName = (TextView)findViewById(R.id.textLastName);
textFirstName.setText("TestFirstName");
textLastName.setText("textLastName");
}
// This was the new way to do using data binding
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
User myUser = new User("TestFirstName", "TestLastName");
binding.setUser(myUser);
}
Data
binding also do automatic null checks, which is really cool. If you want to
access the name, but user is null,
how much of pain in the neck would it be to write user null ? null : user.firstName
null ? :? You don’t want to do that. Now, if contact is null, the whole
expression in null.
You
can use
Ternary
Operator
<TextView
android:text="@{user.lastName
!= null ? user.lastName : user.name}”/>
Type Conversion
<TextView
android:text="@{String.valueOf(user.age)}"/>
Resources
and String
<TextView
android:padding="@{isBig
? @dimen/bigPadding : @dimen/smallPadding}"/>
String
formatting
<TextView
android:text="@{@string/nameFormat(firstName,
lastName)}"/>
Inline
plurals
<TextView
android:text="@{@plurals/employee(employeeCount)}"/>
Imports
<data>
<import type="com.androidjavapoint.User"/>
<import
type="java.util.List"/>
<variable name="user"
type="User"/>
<variable
name="userList" type="List<User>"/>
</data>
Event
Handling
Using
data binding you can also handle events right from the layout xml using either
1. Method
references, or
2. Listener
bindings
Method
References
Events
can be bound to handler methods directly, similar to the way android:onClick
can be assigned to a method in an Activity. One major advantage compared to the
View#onClick attribute is that the expression is processed at compile time, so
if the method does not exist or its signature is not correct, you receive a
compile time error.
For
example, we create a class ActivityHandler, with a simple method called
onButtonClick to handle button clicks like-
public
class ActivityHandler {
public void onButtonClick (View view) {
// do stuff
}
}
In
the layout file, declare ActivityHandler variable, and set the Button
android:onClick using “@{buttonHandler:: onButtonClick }”.
<?xml
version="1.0" encoding="utf-8"?>
<layout
xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable
name="buttonHandler"
type="com.androidjavapoint.databindingsample.ActivityHandler"/>
</data>
<RelativeLayout>
...
<Button
android:id="@+id/finishActivityButton"
android:onClick="@{buttonHandler::onButtonClick}"/>
</RelativeLayout>
</layout>
Listener
Bindings
These
are lambda expressions that are evaluated when the event happens. Data binding
always creates a listener, which it sets on the view. When the event is
dispatched, the listener evaluates the lambda expression.
public
class Presenter {
public void onSaveClick(Task task){}
}
Then
you can bind the click event to your class as follows:
<?xml version="1.0"
encoding="utf-8"?>
<layout
xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable name="task"
type=" com.androidjavapoint.databindingsample Task" />
<variable
name="presenter" type=" com.androidjavapoint.databindingsample.Presenter"
/>
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="@{() ->
presenter.onSaveClick(task)}" />
</LinearLayout>
</layout>
Observable
Objects
Another
way to achieve data change notifications involves the use of Observable
objects. These are objects that either implement the Observable interface, or extend the BaseObservable class.
In
case of implementing Observer interface in each setter method, called notifyPropertyChanged() method, and for
each getter, add @Bindable
annotation.
BaseObservable class:
Suppose
you have User class and used it in the layout xml to populate data on UI. So while extending it via BaseObservable class along with required
changes as mention then whenever the value of User gets change it will notify directly to UI.
BaseObservable
private static class User extends BaseObservable {
private String firstName;
private String lastName;
@Bindable
public String getFirstName() {
return this.firstName;
}
@Bindable
public String getLastName() {
return this.lastName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
notifyPropertyChanged(BR.firstName);
}
public void setLastName(String lastName) {
this.lastName = lastName;
notifyPropertyChanged(BR.lastName);
}
}
private static class User extends BaseObservable {
private String firstName;
private String lastName;
@Bindable
public String getFirstName() {
return this.firstName;
}
@Bindable
public String getLastName() {
return this.lastName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
notifyPropertyChanged(BR.firstName);
}
public void setLastName(String lastName) {
this.lastName = lastName;
notifyPropertyChanged(BR.lastName);
}
}
The
Bindable annotation generates an entry in the BR class file during compilation.
The BR class is generated file like R class. Here notify is done by adding
notifyPropertyChanged.
Observable interface:
Android
data binding gives you the PropertyChangeRegistry class that lets you
essentially take those callbacks and notify them.
Observer
public class User implements Observable {
private PropertyChangeRegistry registry = new PropertyChangeRegistry();
private String firstName;
private String lastName;
@Bindable
public String getFirstName() {
return this.firstName;
}
@Bindable
public String getLastName() {
return this.lastName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
registry.notifyChange(this, BR.firstName);
}
public void setLastName(String lastName) {
this.lastName = lastName;
registry.notifyChange(this, BR.lastName);
}
@Override
public void addOnPropertyChangedCallback(OnPropertyChangedCallback callback) {
registry.add(callback);
}
@Override
public void removeOnPropertyChangedCallback(OnPropertyChangedCallback callback) {
registry.remove(callback);
}
}
public class User implements Observable {
private PropertyChangeRegistry registry = new PropertyChangeRegistry();
private String firstName;
private String lastName;
@Bindable
public String getFirstName() {
return this.firstName;
}
@Bindable
public String getLastName() {
return this.lastName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
registry.notifyChange(this, BR.firstName);
}
public void setLastName(String lastName) {
this.lastName = lastName;
registry.notifyChange(this, BR.lastName);
}
@Override
public void addOnPropertyChangedCallback(OnPropertyChangedCallback callback) {
registry.add(callback);
}
@Override
public void removeOnPropertyChangedCallback(OnPropertyChangedCallback callback) {
registry.remove(callback);
}
}
ObservableField
The
observer using @Bindable and notifyPropertyChanged getters and setters in model
class User is bulky Right? They
clutter up the code and force us to do a lot of routine work.
ObservableField
are autonomous observable objects with one field. You can access them with
get() and set() methods that automatically notify View about changes. To use it
you need to create a public final field in your class.
public
class User {
public final ObservableField<String>
firstname = new ObservableField<>();
public final ObservableField<String>
lastname = new ObservableField<>();
}
In
Java class access getter and setter looks like-
user.firstName.set("TestName");
String
= user.lastName.get();
You
can use these as normal properties in binding expressions:
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{user.firstName}"/>
ObservableMap
With
the ObservableMap, you can access values in your map like any normal map and
the UI will be updated when changes occur.
<data>
<variable name="user"
type="android.databinding.ObservableMap<String,
Object>"/>
</data>
<!--
... -->
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=' @{user["firstName"]}
'/>
And
you’d use the ObservableMap in your code:
ObservableMap<String,
Object> user = new ObservableArrayMap<>();
binding.setUser(user);
user.put("firstName",
"Test Name");
Any
time the product object changes, it will update the UI.
BindingAdapter
Sometimes
we want to do something more complex than simply calling a setter on the View.
You can use
it to redefine the behavior of the existing attributes and create your own
attributes without thinking about attrs.xml. A very common example is loading
images off the UI thread.
In
order to do it you need to create a public static method accepting as input
View of the necessary type and value we specify in the layout. The method
itself should have @BindingAdapter annotation and in its body you should
specify string with the name of the attribute.
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:imageUrl="@{user.imageUrl}"/>
If
we did not do anything then data binding system would look for a setImageUrl() method on ImageView and
not find it. Here we have created a way to set the “app:imageUrl” attribute. You can also use default “android:src”
attribute instead of create own.
@BindingAdapter("imageUrl")
public
static void setImageUrl(ImageView imageView, String url) {
if (url == null) {
imageView.setImageDrawable(null);
} else {
// load image from URL
}
}
As
you can see now we can do whatever we want in that code. We can now load off
the UI thread, just like we want to.
Conclusion
As
we have noticed Android data binding is a very interesting and powerful feature
and it can simplify a lot app building. It avoids the use of reflection and
generates binding classes at compile time for layouts you indicate will use
data binding. Also, the view hierarchy is only traversed once to find your
views. For a more in depth and longer discussion, check out the data binding
android developer article.
To
find more interesting topics on Software development follow me at
https://medium.com/@ankit.sinhal
You
can also find my Android Applications on play store
The blog gave me idea about the android data binding My sincere thanks for sharing this post and please continue to share this post
ReplyDeleteAndroid Training in Chennai
really you have posted an informative blog. it will be really helpful to many peoples. so keep on sharing such kind of an interesting blogs.
ReplyDeleteandroid training in chennai
This book is highly recommended for Android developers as the book contains the best part in Android application development. I would like to suggest refer Android studio by Google which is also a good guide on development.
ReplyDeleteAndroid Training in Chennai | Cloud Computing Training in Chennai
We share this kind of information very useful.Google update for many thinks apps applications.I suggest android studio google guide of development.Are looking for Big Data Developer Course reach us,Want to be looking learn now Big Data Developer reach Hadoop Training in Chennai
ReplyDeleteVery informative ..i suggest this blog to my friends..Thank you for sharing
ReplyDeleteAndroid training in chennai with placement | Android Training in chennai |Android Training in Velachery
You provide a very good information.Really you are a skilled blogger.Thanks for sharing. keep sharing more blogs.
ReplyDeleteAndroid Training in Chennai
Thank you for sharing such an informative post.
ReplyDeleteAndroid Training in velachery also provide excellent android training with real time experience.
This comment has been removed by the author.
ReplyDeleteThis comment has been removed by the author.
ReplyDelete
ReplyDeleteA very interesting case study
Mainframe Training In Chennai | Hadoop Training In Chennai | ETL Testing Training In Chennai
I would say while reading your article i felt very proud, because the information you written very useful, please keep posting this type of articles. If you guys looking for a training institutes for Android Training in Chennai. Please click below link. Best Android Training Institute in Chennai | Best Android Training Course in Chennai or call me at +91 86818 84318
ReplyDeleteThank you for your post. This is excellent information. It is amazing and wonderful to visit your site. keep posting
ReplyDeleteBest Software Training Centre in Chennai | Software Training Centre in Chennai
Great post and informative blog.it was awesome to read, thanks for sharing this great content to my vision.
ReplyDeleteembedded rtos training in chennai | embedded testing training in chennai .
Really Nice post.I am very happy to see this post sharing.A lot of thanks.
ReplyDeleteFinal Year Android Project Centres Chennai | Final Year Embedded Project Centres Chennai.
Nice blog. Thanks for sharing such great information. Hire Sencha Touch Developers ,
ReplyDeleteAndroid app development company
I believe there are many more pleasurable opportunities ahead for individuals that looked at your site. RPA Training in Chennai | Blue Prism Training in Chennai
ReplyDeleteWonderful blog, keep up the good work and share more like this.
ReplyDeleteAngularjs Training in Chennai
Angularjs Training in Velachery
Angular 2 Training in Chennai
ReactJS Training Institutes in Chennai
RPA Training in Chennai
UiPath Training in Chennai
Blue Prism Training in Chennai
Data Science Training in Chennai
Very well written post! Thanks for sharing.
ReplyDeleteTally Course in Chennai
Tally Classes in Chennai
Tally Training in Chennai
Spark Training Academy Chennai
VMware Training Center in Chennai
WordPress Training Institute in Chennai
You are doing a great job.
ReplyDeleteRegards,
Data Science Course in Chennai | Data Science Training Institute
Really awesome blog. Your blog is really useful for me
ReplyDeleteRegards,
Data Science Course in Chennai
its a good post and keep posting good article.its very interesting to read.
ReplyDeleteRegards,
Data Science Course in Chennai | R Programming Training in Chennai | Python Training in Chennai
Thanks for the wonderful tip! Very detailed and informative. Easy enough for a beginner like me to understand.
ReplyDeleteData Science Training in Chennai | Data Science Course in Chennai
Hey, would you mind if I share your blog with my twitter group? There’s a lot of folks that I think would enjoy your content. Please let me know. Thank you.
ReplyDeleteAzure Training in Chennai | Best Azure Training in Chennai
Salesforce Training in Chennai | Best Salesforce Training in Chennai
PowerBI Training in Chennai | Best PowerBI Training in Chennai
MSBI Training in Chennai | Best MSBI Training in Chennai
Java Training in Chennai | Best Java Training in Chennai
Software Testing Training in Chennai | Best Software Testing Training in Chennai
Me2call4u is just what it sounds like - a place to meet new friends. With Me2call4u, you can find new friendships from your own city or from around the world. Random video chat
ReplyDeletenice post...
ReplyDeleteforeach loop in node js
ywy cable
javascript integer max value
adder and subtractor using op amp
"c program to find frequency of a word in a string"
on selling an article for rs 1020, a merchant loses 15%. for how much price should he sell the article to gain 12% on it ?
paramatrix interview questions
why you consider yourself suitable for the position applied for
great blog
ReplyDeleteInplant Training in Chennai
Iot Internship
Internship in Chennai for CSE
Internship in Chennai
Python Internship in Chennai
Implant Training in Chennai
Android Training in Chennai
R Programming Training in Chennai
Python Internship
Internship in chennai for EEE
nice blog.
ReplyDeleteAcceptance is to offer what a lighted
A reduction of 20 in the price of salt
Power bi resumes
Qdxm:sfyn::uioz:?
If 10^0.3010 = 2, then find the value of log0.125 (125) ?
A dishonest dealer professes to sell his goods at cost price but still gets 20% profit by using a false weight. what weight does he substitute for a kilogram?
Oops concepts in c# pdf
Resume for bca freshers
Attempt by security transparent method 'webmatrix.webdata.preapplicationstartcode.start()' to access security critical method 'system.web.webpages.razor.webpagerazorhost.addglobalimport(system.string)' failed.
Node js foreach loop
Good..
ReplyDeletecse internship in hyderabad
companies for industrial visit in chennai for cse students
winter internship for mechanical engineering students
internship training in bangalore
ece internships in bangalore
free internship in chennai for mechanical engineering students
internship with stipend for ece
ai internship in chennai
internship certificate for mechanical engineering students
internships in chennai for ece students
awesome bloggers....!
ReplyDeletepoland web hosting
russian federation web hosting
slovakia web hosting
spain web hosting
suriname
syria web hosting
united kingdom
united kingdom shared web hosting
zambia web hosting
inplant training in chennai
Great information....
ReplyDeleteIntern Ship In Chennai
Inplant Training In Chennai
Internship For CSE Students
Online Internships
Coronavirus Update
Internship For MBA Students
iot internship