SlideShare a Scribd company logo
1 of 80
Download to read offline
Dominando o Data Binding

no Android
+Nelson Glauber
@nglauber
www.nglauber.com.br
@nglauber
+NelsonGlauber
www.nglauber.com.br
Por que Data Binding?
Data Binding
• Facilita a ligação entre Model e View
• Estende os arquivos de layout com micro-expressões
• Binders customizados reduzem a repetição de código
• Tratamento de NPE
Estudo de caso
public class Book {
private String id;
private String title;
private String author;
private String coverUrl;
private int pages;
private int year;
private Publisher publisher;
private boolean available;
private MediaType mediaType;
private float rating;
// Getters and setters...
}
Book book = (Book)getIntent().getSerializableExtra(EXTRA_LIVRO);
ImageView imgCover = (ImageView) findViewById(R.id.image_cover);
TextView txtTitle = (TextView) findViewById(R.id.text_title);
TextView txtAuthor = (TextView) findViewById(R.id.text_author);
TextView txtPages = (TextView) findViewById(R.id.text_pages);
TextView txtYear = (TextView) findViewById(R.id.text_year);
TextView txtPublisher = (TextView) findViewById(R.id.text_publisher);
TextView txtAvailable = (TextView) findViewById(R.id.text_available);
TextView txtMediaType = (TextView) findViewById(R.id.text_media_type);
RatingBar ratingBook = (RatingBar) findViewById(R.id.rating_book);
Glide.with(this).load(book.getCoverUrl()).into(imgCover);
txtTitle.setText(book.getTitle());
txtAuthor.setText(book.getAuthor());
txtPages.setText(getString(R.string.text_format_book_pages, book.getPages()));
txtYear.setText(getString(R.string.text_format_book_year, book.getYear()));
txtPublisher.setText(book.getPublisher().getName());
txtAvailable.setText(book.isAvailable() ?
R.string.text_book_available : R.string.text_book_unavailable);
txtMediaType.setText(book.getMediaType().toString());
ratingBook.setNumStars(book.getRating());
book.setCoverUrl(imageFile.getAbsolutePath());
book.setTitle(editPages.getText().toString());
book.setAuthor(editAuthor.getText().toString());
book.setPages(Integer.parseInt(editPages.getText().toString()));
book.setYear(Integer.parseInt(editYear.getText().toString()));
book.setPublisher((Publisher) spinnerPublisher.getSelectedItem());
book.setAvailable(checkAvailable.isChecked());
book.setMediaTypeValue(radioMediaEbook.isChecked() ?

MediaType.EBOOK : MediaType.PAPER);
book.setRating(ratingBook.getRating());
saveBook(book);
Book book = (Book)getIntent().getSerializableExtra(EXTRA_BOOK);
ActivityDetailViewBinding mBinding =

DataBindingUtil.setContentView(this, R.layout.activity_detail_view);
mBinding.setBook(book);
Conceitos básicos
Configuração
Passo 1…
android {
...
dataBinding {
enabled true
}
}
…e pronto!
res/layout/activity_main.xml
activity_main.xml
ActivityMainBinding
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<LinearLayout ...>
<TextView ...
android:id=“@+id/text_view_name”
android:text="Hello World!" />
</LinearLayout>
</layout>
public class MainActivity extends AppCompatActivity {
ActivityMainBinding mBinding;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mBinding = DataBindingUtil.setContentView(this, R.layout.activity_main);
mBinding.textViewName.setText(“DataBinding is cool!!!”);
}
}
MainActivity.java
camelCase
Se não gostar do nome da classe…
MainActivity.java
res/layout/activity_main.xml
<layout ...>
<data class="VaiFilhaoBinding">
...
</data>
public class MainActivity extends AppCompatActivity {
VaiFilhaoBinding binding;
...
Mapeando objetos na UI
Book book = (Book)getIntent().getSerializableExtra(EXTRA_LIVRO);
ImageView imgCover = (ImageView) findViewById(R.id.image_cover);
TextView txtTitle = (TextView) findViewById(R.id.text_title);
TextView txtAuthor = (TextView) findViewById(R.id.text_author);
TextView txtPages = (TextView) findViewById(R.id.text_pages);
TextView txtYear = (TextView) findViewById(R.id.text_year);
TextView txtPublisher = (TextView) findViewById(R.id.text_publisher);
TextView txtAvailable = (TextView) findViewById(R.id.text_available);
TextView txtMediaType = (TextView) findViewById(R.id.text_media_type);
RatingBar ratingBook = (RatingBar) findViewById(R.id.rating_book);
Glide.with(this).load(book.getCoverUrl()).into(imgCover);
txtTitle.setText(book.getTitle());
txtAuthor.setText(book.getAuthor());
txtPages.setText(getString(R.string.text_format_book_pages, book.getPages()));
txtYear.setText(getString(R.string.text_format_book_year, book.getYear()));
txtPublisher.setText(book.getPublisher().getName());
txtAvailable.setText(book.isAvailable() ?
R.string.text_book_available : R.string.text_book_unavailable);
txtMediaType.setText(book.getMediaType().toString());
ratingBook.setNumStars(book.getRating());
Book book = (Book)getIntent().getSerializableExtra(EXTRA_BOOK);
ActivityDetailViewBinding mBinding =

DataBindingUtil.setContentView(this, R.layout.activity_detail_view);
mBinding.setBook(book);
<layout xmlns:android="http://schemas.android.com/apk/res/android" ...>
<data>
<variable
name="book"
type="br.com.nglauber.livrosfirebase.model.Book" />
</data>
<LinearLayout ... >
<ImageView android:src="@{book.coverUrl}" ... />
<TextView android:text="@{book.title}" ... />
<TextView android:text="@{book.author}" ... />
<TextView android:text="@{@string/text_format_book_pages(book.pages)}" ... />
<TextView android:text="@{@string/text_format_book_year(book.year)}" ... />
<TextView android:text="@{book.publisher.name}" ... />
<TextView android:text="@{book.available ?
@string/text_book_available :
@string/text_book_unavailable}" ... />
<TextView android:text="@{book.mediaType}" ... />
<RatingBar android:rating="@{book.rating}" ... />
</LinearLayout>
</layout>
<layout xmlns:android="http://schemas.android.com/apk/res/android" ...>
<data>
<variable
name="book"
type="br.com.nglauber.livrosfirebase.model.Book" />
</data>
<LinearLayout ... >
<ImageView android:src="@{book.coverUrl}" ... />
<TextView android:text="@{book.title}" ... />
<TextView android:text="@{book.author}" ... />
<TextView android:text="@{@string/text_format_book_pages(book.pages)}" ... />
<TextView android:text="@{@string/text_format_book_year(book.year)}" ... />
<TextView android:text="@{book.publisher.name}" ... />
<TextView android:text="@{book.available ?
@string/text_book_available :
@string/text_book_unavailable}" ... />
<TextView android:text="@{book.mediaType}" ... />
<RatingBar android:progress="@{book.rating}" ... />
</LinearLayout>
</layout>
<!-- strings.xml -->
<string name="text_format_book_pages">Número de páginas: %1$d</string>
<string name="text_format_book_year">Ano de publicação: %1$d</string>
<layout xmlns:android="http://schemas.android.com/apk/res/android" ...>
<data>
<variable
name="book"
type="br.com.nglauber.livrosfirebase.model.Book" />
</data>
<LinearLayout ... >
<ImageView android:src="@{book.coverUrl}" ... />
<TextView android:text="@{book.title}" ... />
<TextView android:text="@{book.author}" ... />
<TextView android:text="@{@string/text_format_book_pages(book.pages)}" ... />
<TextView android:text="@{@string/text_format_book_year(book.year)}" ... />
<TextView android:text="@{book.publisher.name}" ... />
<TextView android:text="@{book.available ?
@string/text_book_available :
@string/text_book_unavailable}" ... />
<TextView android:text="@{book.mediaType}" ... />
<RatingBar android:progress="@{book.rating}" ... />
</LinearLayout>
</layout>
Tá pronto? Pode
rodar???
NÃO!
<layout xmlns:android="http://schemas.android.com/apk/res/android" ...>
<data>
<variable
name="book"
type="br.com.nglauber.livrosfirebase.model.Book" />
</data>
<LinearLayout ... >
<ImageView android:src="@{book.coverUrl}" ... />
<TextView android:text="@{book.title}" ... />
<TextView android:text="@{book.author}" ... />
<TextView android:text="@{@string/text_format_book_pages(book.pages)}" ... />
<TextView android:text="@{@string/text_format_book_year(book.year)}" ... />
<TextView android:text="@{book.publisher.name}" ... />
<TextView android:text="@{book.available ?
@string/text_book_available :
@string/text_book_unavailable}" ... />
<TextView android:text="@{book.mediaType}" ... />
<RatingBar android:progress="@{book.rating}" ... />
</LinearLayout>
</layout>
public class Book {
...
private String coverUrl;
private MediaType mediaType;
}
Binding Adapters #1
public class TextBinding {
@BindingAdapter({"android:text"})
public static void setMediaTypeText(TextView textView, MediaType mediaType){
Context context = textView.getContext();
switch (mediaType) {
case EBOOK:
textView.setText(context.getString(R.string.text_book_media_ebook));
break;
case PAPER:
textView.setText(context.getString(R.string.text_book_media_paper));
break;
default:
textView.setText(null);
}
}
}
TextBinding.java
public class ImageBinding {
@BindingAdapter({"android:src"})
public static void setImageUrl(ImageView imageView, String url){
Glide.with(imageView.getContext())
.load(url)
.into(imageView);
}
@BindingAdapter({"android:src", "placeHolder"})
public static void setImageUrl(ImageView imageView, String url,
Drawable placeholder){
Glide.with(imageView.getContext())
.load(url)
.placeholder(placeholder)
.into(imageView);
}
}
ImageBinding.java
<ImageView
android:id="@+id/image_cover"
android:layout_width="200dp"
android:layout_height="200dp"
android:layout_gravity="center"
android:background="#CCC"
android:scaleType="centerCrop"
android:src="@{book.coverUrl}"
app:placeHolder=“@{@drawable/ic_photo}”/>
res/values/attrs.xml
<attr name="placeHolder" format="reference"/>
Fragments e Adapters
BookFragment.java
private FragmentBookBinding mBinding;
@Override
public View onCreateView(LayoutInflater inflater,
ViewGroup container,
Bundle savedInstanceState) {
mBinding = DataBindingUtil.inflate(inflater,
R.layout.fragment_book,
container, false);
...
return mBinding.getRoot();
}
res/layout/item_book.xml
<layout ...>
<data>
<variable
name="book"
type="br.com.nglauber.livrosfirebase.model.Book"/>
</data>
<android.support.v7.widget.CardView ...>
<RelativeLayout ...>
<ImageView android:src="@{book.coverUrl}" ... />
<TextView android:text="@{book.title}" ... />
<TextView android:text="@{book.author}" ... />
</RelativeLayout>
</android.support.v7.widget.CardView>
</layout>
BookViewHolder.java
public static class BookViewHolder extends RecyclerView.ViewHolder {
ItemBookBinding binding;
public BookViewHolder(ItemBookBinding binding) {
super(binding.getRoot());
this.binding = binding;
}
}
@Override
public BookViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
ItemBookBinding binding = DataBindingUtil.inflate(
LayoutInflater.from(parent.getContext()),
R.layout.item_book,
parent,
false);
final BookViewHolder vh = new BookViewHolder(binding);
vh.itemView.setOnClickListener(...);
return vh;
}
@Override
public void onBindViewHolder(BookViewHolder holder, int pos) {
Book book = mBooksList.get(pos);
holder.binding.setBook(book);
holder.binding.executePendingBindings();
}
BookAdapter.java
E se os dados mudarem?
public class Book extends BaseObservable {
// Atributos...
@Bindable
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
notifyPropertyChanged(BR.title);
}
@Bindable
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
notifyPropertyChanged(BR.author);
}
// Demais getters/setters
Book.java
public class Book implements Observable {
// Copie as coisas do BaseObservable :)
}
public class BaseObservable implements Observable {
private transient PropertyChangeRegistry mCallbacks;
public BaseObservable() {
}
@Override
public synchronized void addOnPropertyChangedCallback(OnPropertyChangedCallback callback) {
if (mCallbacks == null) {
mCallbacks = new PropertyChangeRegistry();
}
mCallbacks.add(callback);
}
@Override
public synchronized void removeOnPropertyChangedCallback(OnPropertyChangedCallback callback) {
if (mCallbacks != null) {
mCallbacks.remove(callback);
}
}
public synchronized void notifyChange() {
if (mCallbacks != null) {
mCallbacks.notifyCallbacks(this, 0, null);
}
}
public void notifyPropertyChanged(int fieldId) {
if (mCallbacks != null) {
mCallbacks.notifyCallbacks(this, fieldId, null);
}
}
}
import android.databinding.ObservableBoolean;
import android.databinding.ObservableField;
import android.databinding.ObservableInt;
public class Book {
//...
private final ObservableField<String> title;
private final ObservableInt year;
private final ObservableBoolean available;
public Book() {
//...
this.title = new ObservableField<>();
this.year = new ObservableInt(2016);
this.available = new ObservableBoolean(false);
}
public ObservableField<String> getTitle() { return title; }
public void setTitle(String title) { this.title.set(title); }
public ObservableInt getYear() { return year; }
public void setYear(double year) { this.year.set(year); }
public ObservableBoolean isAvailable() { return available; }
public void setAvailable(boolean available) { this.available.set(available); }
}
Two-way Data Binding
<layout ...>
<data>
<variable name="texto" type="String"/>
</data>
<LinearLayout ... >
<TextView ...
android:id="@+id/textViewNome"
android:text="@{texto}" />
<EditText ...
android:id="@+id/editTextNome"
android:text="@={texto}"/>
</LinearLayout>
</layout>
<layout ...>
<data>
...
<import type="br.com.nglauber.livrosfirebase.model.MediaType" />
<variable name="book"
type="br.com.nglauber.livrosfirebase.model.Book" />
</data>
<LinearLayout ...>
<ImageView android:src="@{book.coverUrl}" ... />
<EditText android:text="@={book.title}" ... />
<EditText android:text="@={book.author}" ... />
<EditText android:text="@={book.pages}" ... />
<EditText android:text="@={book.year}" ... />
<Spinner ...> <!-- trataremos desse em breve. -->
<CheckBox android:checked="@={book.available}" ... />
<RadioGroup ...>
<RadioButton ...
android:checked="@{book.mediaTypeValue == MediaType.EBOOK}" ... />
<RadioButton ...
android:checked="@{book.mediaTypeValue == MediaType.PAPER}" ... />
</RadioGroup>
<RatingBar
android:rating="@={book.rating}" ... />
...
</LinearLayout>
</layout>
<layout ...>
<data>
...
<import type="br.com.nglauber.livrosfirebase.model.MediaType" />
<variable name="book"
type="br.com.nglauber.livrosfirebase.model.Book" />
</data>
<LinearLayout ...>
<ImageView android:src="@{book.coverUrl}" ... />
<EditText android:text="@={book.title}" ... />
<EditText android:text="@={book.author}" ... />
<EditText android:text="@={book.pages}" ... />
<EditText android:text="@={book.year}" ... />
<Spinner ...> <!-- trataremos desse em breve. -->
<CheckBox android:checked="@={book.available}" ... />
<RadioGroup ...>
<RadioButton ...
android:checked="@{book.mediaTypeValue == MediaType.EBOOK}" ... />
<RadioButton ...
android:checked="@{book.mediaTypeValue == MediaType.PAPER}" ... />
</RadioGroup>
<RatingBar
android:progress="@={book.rating}" ... />
...
</LinearLayout>
</layout>
Binding Adapters #2
Cuidado com loops!
EditText

android:text="@={book.title}"
public class Book extends BaseObservable {
// Atributos...
@Bindable
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
notifyPropertyChanged(BR.title);
}
// Demais getters/setters
public class EditTextBindingAdapters {
@InverseBindingAdapter(attribute = "android:text")
public static int getTextAsInt(EditText editText) {
try {
return Integer.parseInt(editText.getText().toString());
} catch (Exception e){
return 0;
}
}
@BindingAdapter({"android:text"})
public static void setTextFromInt(EditText editText, int value){
if (getTextAsInt(editText) != value) {
editText.setText(String.valueOf(value));
}
}
}
EditTextBindingAdapters.java
Tratamento de eventos
<layout ...>
<data>
...
<variable
name="presenter"
type=“br.com.nglauber.livrosfirebase.DetailEditActivity"/>
</data>
<LinearLayout ...>
...
<TextView ...
android:onLongClick="@{presenter::longClick}" />
<Button ...
android:onClick=“@{presenter::clickSaveBook}”/>
<EditText ...
android:onFocusChange="@{presenter::focusChanged}"/>
</LinearLayout>
</layout>
res/layout/activity_detail_edit.xml
@Override
protected void onCreate(Bundle savedInstanceState) {
...
binding.setBook(book);
binding.setPresenter(this);
}
public void clickSaveBook(View view) {
Toast.makeText(this, book.toString(), Toast.LENGTH_SHORT).show();
}
public boolean longClick(View view){
book.setRating(book.getRating() + 1);
return true;
}
public void focusChanged(View v, boolean focus){
if (!focus) showProduct(v);
}
DetailEditActivity.java
Respeite a
assinatura do
método
<layout ...>
<data>
<import type="br.com.nglauber.livrosfirebase.model.MediaType" />
...
<variable
name="presenter"
type="br.com.nglauber.livrosfirebase.DetailEditActivity" />
</data>
<LinearLayout ...>
...
<RadioGroup ...>
<RadioButton ...
android:checked="@{book.mediaTypeValue == MediaType.EBOOK}"
android:onCheckedChanged="@{presenter::onMediaTypeChanged}" />
<RadioButton ...
android:checked="@{book.mediaTypeValue == MediaType.PAPER}"
android:onCheckedChanged="@{presenter::onMediaTypeChanged}" />
</RadioGroup>
...
</LinearLayout>
</layout>
public void onMediaTypeChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked) {
if (buttonView == mBinding.radioMediaEbook) {
mBinding.getBook().setMediaTypeValue(MediaType.EBOOK);
} else if (buttonView == mBinding.radioMediaPaper) {
mBinding.getBook().setMediaTypeValue(MediaType.PAPER);
}
}
}
public class Publisher {
private String id;
private String name;
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return name;
}
}
public class Book extends BaseObservable {
private Publisher publisher;
...
@Bindable
public Publisher getPublisher() {
return publisher;
}
public void setPublisher(Publisher publisher) {
this.publisher = publisher;
notifyPropertyChanged(BR.publisher);
}
}
<layout ...>
<data>
<import type="java.util.List"/>
<variable name="book"
type="br.com.nglauber.livrosfirebase.model.Book" />
<variable name="presenter"
type="br.com.nglauber.livrosfirebase.DetailEditActivity" />
<variable name="publishers"
type="java.util.List&lt;br.com.nglauber.livrosfirebase.model.Publisher&gt;" />
</data>

<LinearLayout ...>
<Spinner ...
android:entries="@{publishers}"
android:selection="@{publishers.indexOf(book.publisher)}"
android:onItemSelected="@{(p, v, pos, id)->book.setPublisher(publishers[pos])}" />
</LinearLayout>
</layout>
DetailEditActivity.java
ObservableList<Publisher> publishers = loadListFromSomewhere();
mBinding.setPublishers(publishers);
<layout ...>
<data>
<variable
name="book"
type="br.com.nglauber.livrosfirebase.model.Book"/>
<variable
name="presenter"
type=“br.com.nglauber.livrosfirebase.DetailEditActivity"/>
</data>
<LinearLayout ...>
...
<Button ...
android:onClick="@{()->presenter.saveBook(book)}"/>
</LinearLayout>
</layout>
Pronto!
http://jakewharton.github.io/butterknife/
Binding Adapters #3
https://github.com/lisawray/fontbinding
public class TextViewBinderAdapter {
@BindingAdapter({"font"})
public static void setFont(TextView textView,String font){
AssetManager assets = textView.getContext().getAssets();
Typeface typeface = Typeface.createFromAsset(assets, font);
textView.setTypeface(typeface);
}
}
<TextView app:font="@{`FunnyKid.ttf`}" .../>
Mas se tiver um “set” pode usar!
<android.support.v4.widget.DrawerLayout ...
app:scrimColor="@{@color/scrim}"
app:drawerListener="@{fragment.drawerListener}"/>
Miscellaneous
Expression Language
<TextView ...
android:text="@{user.displayName ?? user.lastName}"/>
<TextView ...
android:text="@{`User: ` + user.name}”/>
<LinearLayout ...
android:padding="@{large? @dimen/largePadding : @dimen/smallPadding}"/>
res/values/colors.xml
<color name="red">#F00</color>
<color name="black">#000</color>
<TextView ...
android:id="@+id/text_title"
android:textColor="@{book.available ? @color/black : @color/red}"
android:text="@{book.title}" />
res/values/strings.xml
<string name="price_format">$ %1$.2f</string>
<TextView ...
android:id="@+id/text_price"
android:text="@{@string/price_format(book.price)}" />
getString(R.string.price_format, product.price);
Include
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<data>
<variable name="book" type=“...Book”/>
<variable name=“presenter" type=“...DetailEditActivity" />
</data>
<LinearLayout ...>
<include
android:id="@+id/content"
layout="@layout/content_detail_edit"
app:presenter="@{presenter}"
app:book="@{book}" />
</LinearLayout>
</layout>
Include
ActivityDetailEditBinding mBinding =
DataBindingUtil.setContentView(this, R.layout.activity_detail_edit);
mBinding.setBook(book);
mBinding.setPresenter(this);
mBinding.content.setPublishers(new ObservableArrayList<Publisher>());
Expression Chain
<layout ...>
<data>
<import type="android.view.View" />
...
</data>
<LinearLayout ...>
<ImageView ...
android:id="@+id/image_cover"
android:visibility="@{book.available ? View.VISIBLE : View.INVISIBLE}" />
<RadioGroup ...
android:id="@+id/radio_group_media_type"
android:visibility="@{imageCover.visibility}" />
<RatingBar
android:visibility="@{radioGroupMediaType.visibility}"
android:id=“@+id/rating_book">
<CheckBox ...
android:id="@+id/check_available"
android:checked="@={book.available}" />
Ouvindo coisas… :)
binding.addOnPropertyChangedCallback(new Observable.OnPropertyChangedCallback() {
@Override
public void onPropertyChanged(Observable observable, int i) {
if (i == br.com.nglauber.uidemo.BR.name){
Product p = (Product)observable;
Log.d("NGVL", p.getName());
}
}
});
Ouvindo coisas… :)
Use para
animações
binding.addOnRebindCallback(new OnRebindCallback() {
@Override
public boolean onPreBind(ViewDataBinding binding) {
return super.onPreBind(binding);
}
@Override
public void onCanceled(ViewDataBinding binding) {
super.onCanceled(binding);
}
@Override
public void onBound(ViewDataBinding binding) {
super.onBound(binding);
}
});
Aplicando no seu projeto
1. Remova os findViewById’s :)
2. Faça o Binding dos seus objetos.
3. Use os callbacks (eventos) de UI.
4. Aproveite os objetos observáveis.
5. Two-way Data Binding é vida! ♥
Boas práticas
• Não coloque lógica de negócios na tela. Apenas lógica de tela.
• Os eventos disparados executarão na UI Thread.
• Simplifique a lógica de UI (não coloque expressões complicadas,
crie métodos para isso.
• Considere utilizar um ViewModel.
• Leve os BinderAdapters com você :) Você só vai precisar escrevê-
los uma vez. // TODO: Fazer uma lib para isso :p
Referências
• Data Binding -- Write Apps Faster (Android Dev Summit 2015)

https://www.youtube.com/watch?v=NBbeQMOcnZ0
• Data Binding Documentation (pode melhorar né…?)

http://developer.android.com/tools/data-binding/guide.html
• Nelson Glauber Blog

http://www.nglauber.com.br/2016/05/android-data-binding.html
• Advanced Data Binding (Google I/O 2016)

https://www.youtube.com/watch?v=DAmMN7m3wLU
Dúvidas?
@nglauber
+NelsonGlauber
www.nglauber.com.br
Obrigado!

More Related Content

What's hot

CT presentatie JQuery 7.12.11
CT presentatie JQuery 7.12.11CT presentatie JQuery 7.12.11
CT presentatie JQuery 7.12.11
virtualsciences41
 
Intro to Javascript and jQuery
Intro to Javascript and jQueryIntro to Javascript and jQuery
Intro to Javascript and jQuery
Shawn Calvert
 

What's hot (20)

前端MVC之BackboneJS
前端MVC之BackboneJS前端MVC之BackboneJS
前端MVC之BackboneJS
 
Jquery Complete Presentation along with Javascript Basics
Jquery Complete Presentation along with Javascript BasicsJquery Complete Presentation along with Javascript Basics
Jquery Complete Presentation along with Javascript Basics
 
Guia de Sobrevivência JS no mundo Open Source
Guia de Sobrevivência JS no mundo Open SourceGuia de Sobrevivência JS no mundo Open Source
Guia de Sobrevivência JS no mundo Open Source
 
Django workshop : let's make a blog
Django workshop : let's make a blogDjango workshop : let's make a blog
Django workshop : let's make a blog
 
jQuery Presentation
jQuery PresentationjQuery Presentation
jQuery Presentation
 
jQuery for beginners
jQuery for beginnersjQuery for beginners
jQuery for beginners
 
Angular js
Angular jsAngular js
Angular js
 
A Novel Approach to Scraping Websites - Rob Ousbey, MozCon 2020
A Novel Approach to Scraping Websites - Rob Ousbey, MozCon 2020A Novel Approach to Scraping Websites - Rob Ousbey, MozCon 2020
A Novel Approach to Scraping Websites - Rob Ousbey, MozCon 2020
 
Jquery ui
Jquery uiJquery ui
Jquery ui
 
Internet and Web Technology (CLASS-9) [React.js] | NIC/NIELIT Web Technology
Internet and Web Technology (CLASS-9) [React.js] | NIC/NIELIT Web TechnologyInternet and Web Technology (CLASS-9) [React.js] | NIC/NIELIT Web Technology
Internet and Web Technology (CLASS-9) [React.js] | NIC/NIELIT Web Technology
 
CT presentatie JQuery 7.12.11
CT presentatie JQuery 7.12.11CT presentatie JQuery 7.12.11
CT presentatie JQuery 7.12.11
 
jQuery Loves Developers - Oredev 2009
jQuery Loves Developers - Oredev 2009jQuery Loves Developers - Oredev 2009
jQuery Loves Developers - Oredev 2009
 
Intro to Javascript and jQuery
Intro to Javascript and jQueryIntro to Javascript and jQuery
Intro to Javascript and jQuery
 
Лабораторная работа №1
Лабораторная работа №1Лабораторная работа №1
Лабораторная работа №1
 
Entity Relationships in a Document Database at CouchConf Boston
Entity Relationships in a Document Database at CouchConf BostonEntity Relationships in a Document Database at CouchConf Boston
Entity Relationships in a Document Database at CouchConf Boston
 
Intro to jQuery
Intro to jQueryIntro to jQuery
Intro to jQuery
 
TinyMCE: WYSIWYG editor 2010-12-08
TinyMCE: WYSIWYG editor 2010-12-08TinyMCE: WYSIWYG editor 2010-12-08
TinyMCE: WYSIWYG editor 2010-12-08
 
ハンズオン資料 電話を作ろう(v1.6用)
ハンズオン資料 電話を作ろう(v1.6用)ハンズオン資料 電話を作ろう(v1.6用)
ハンズオン資料 電話を作ろう(v1.6用)
 
JSON-LD: JSON for Linked Data
JSON-LD: JSON for Linked DataJSON-LD: JSON for Linked Data
JSON-LD: JSON for Linked Data
 
The Rise of NoSQL
The Rise of NoSQLThe Rise of NoSQL
The Rise of NoSQL
 

Viewers also liked

Viewers also liked (20)

Android Wear DevFest Sudeste 2015
Android Wear DevFest Sudeste 2015Android Wear DevFest Sudeste 2015
Android Wear DevFest Sudeste 2015
 
Google Play Services Rocks!!!
Google Play Services Rocks!!!Google Play Services Rocks!!!
Google Play Services Rocks!!!
 
Android Libs - AndroidDevConf
Android Libs - AndroidDevConfAndroid Libs - AndroidDevConf
Android Libs - AndroidDevConf
 
Aumentando a produtividade com Android Libs
Aumentando a produtividade com Android LibsAumentando a produtividade com Android Libs
Aumentando a produtividade com Android Libs
 
Android FREETEC
Android FREETECAndroid FREETEC
Android FREETEC
 
Android Wear Androidos 2015
Android Wear Androidos 2015Android Wear Androidos 2015
Android Wear Androidos 2015
 
Android DevConference - Refactoring for RxJava
Android DevConference - Refactoring for RxJavaAndroid DevConference - Refactoring for RxJava
Android DevConference - Refactoring for RxJava
 
Conhecendo o Android Wear
Conhecendo o Android WearConhecendo o Android Wear
Conhecendo o Android Wear
 
Campus Party Recife - Sua primeira e próximas aplicações Android: como fazer ...
Campus Party Recife - Sua primeira e próximas aplicações Android: como fazer ...Campus Party Recife - Sua primeira e próximas aplicações Android: como fazer ...
Campus Party Recife - Sua primeira e próximas aplicações Android: como fazer ...
 
Interfaces Inteligentes para Android
Interfaces Inteligentes para AndroidInterfaces Inteligentes para Android
Interfaces Inteligentes para Android
 
Desenvolvimento Android: Faça da maneira certa
Desenvolvimento Android: Faça da maneira certaDesenvolvimento Android: Faça da maneira certa
Desenvolvimento Android: Faça da maneira certa
 
Construindo uma API, Client e Documentação usando Silex, Angular e Swagger
Construindo uma API, Client e Documentação usando Silex, Angular e SwaggerConstruindo uma API, Client e Documentação usando Silex, Angular e Swagger
Construindo uma API, Client e Documentação usando Silex, Angular e Swagger
 
Android DevConference - SOLID no Android
Android DevConference - SOLID no AndroidAndroid DevConference - SOLID no Android
Android DevConference - SOLID no Android
 
Android DevConference - Data Binding: Código limpo, manutenção garantida
Android DevConference - Data Binding: Código limpo, manutenção garantidaAndroid DevConference - Data Binding: Código limpo, manutenção garantida
Android DevConference - Data Binding: Código limpo, manutenção garantida
 
Intro to Silex
Intro to SilexIntro to Silex
Intro to Silex
 
Android DevConference - Live code with Kotlin: construindo o primeiro app usa...
Android DevConference - Live code with Kotlin: construindo o primeiro app usa...Android DevConference - Live code with Kotlin: construindo o primeiro app usa...
Android DevConference - Live code with Kotlin: construindo o primeiro app usa...
 
Orientação a Objetos para Desenvolvedores Android
Orientação a Objetos para Desenvolvedores AndroidOrientação a Objetos para Desenvolvedores Android
Orientação a Objetos para Desenvolvedores Android
 
Api usando Silex
Api usando SilexApi usando Silex
Api usando Silex
 
Android DevConference - Indo além com automação de testes de apps Android
Android DevConference - Indo além com automação de testes de apps AndroidAndroid DevConference - Indo além com automação de testes de apps Android
Android DevConference - Indo além com automação de testes de apps Android
 
Android e iOS: Por que eles são diferentes... ou não.
Android e iOS: Por que eles são diferentes... ou não.Android e iOS: Por que eles são diferentes... ou não.
Android e iOS: Por que eles são diferentes... ou não.
 

Similar to Dominando o Data Binding no Android

Flex3 data binding
Flex3 data bindingFlex3 data binding
Flex3 data binding
guestdf3003
 

Similar to Dominando o Data Binding no Android (20)

Arquitetando seu app Android com Jetpack
Arquitetando seu app Android com JetpackArquitetando seu app Android com Jetpack
Arquitetando seu app Android com Jetpack
 
MVVM & Data Binding Library
MVVM & Data Binding Library MVVM & Data Binding Library
MVVM & Data Binding Library
 
CIRCUIT 2015 - Content API's For AEM Sites
CIRCUIT 2015 - Content API's For AEM SitesCIRCUIT 2015 - Content API's For AEM Sites
CIRCUIT 2015 - Content API's For AEM Sites
 
How to use data binding in android
How to use data binding in androidHow to use data binding in android
How to use data binding in android
 
Introduction to MongoDB
Introduction to MongoDBIntroduction to MongoDB
Introduction to MongoDB
 
Data binding 入門淺談
Data binding 入門淺談Data binding 入門淺談
Data binding 入門淺談
 
Flex3 data binding
Flex3 data bindingFlex3 data binding
Flex3 data binding
 
Android Development Made Easy - With Sample Project
Android Development Made Easy - With Sample ProjectAndroid Development Made Easy - With Sample Project
Android Development Made Easy - With Sample Project
 
Getting Healthy with Magnolia, Blossom and Spring
Getting Healthy with Magnolia, Blossom and SpringGetting Healthy with Magnolia, Blossom and Spring
Getting Healthy with Magnolia, Blossom and Spring
 
Content Management with MongoDB by Mark Helmstetter
 Content Management with MongoDB by Mark Helmstetter Content Management with MongoDB by Mark Helmstetter
Content Management with MongoDB by Mark Helmstetter
 
Android Development for Beginners with Sample Project - Day 1
Android Development for Beginners with Sample Project - Day 1Android Development for Beginners with Sample Project - Day 1
Android Development for Beginners with Sample Project - Day 1
 
Approaches to mobile site development
Approaches to mobile site developmentApproaches to mobile site development
Approaches to mobile site development
 
Dicoding Developer Coaching #19: Android | Menyimpan Database Secara Local di...
Dicoding Developer Coaching #19: Android | Menyimpan Database Secara Local di...Dicoding Developer Coaching #19: Android | Menyimpan Database Secara Local di...
Dicoding Developer Coaching #19: Android | Menyimpan Database Secara Local di...
 
Cordova training : Day 4 - Advanced Javascript
Cordova training : Day 4 - Advanced JavascriptCordova training : Day 4 - Advanced Javascript
Cordova training : Day 4 - Advanced Javascript
 
#NoXML: Eliminating XML in Spring Projects - SpringOne 2GX 2015
#NoXML: Eliminating XML in Spring Projects - SpringOne 2GX 2015#NoXML: Eliminating XML in Spring Projects - SpringOne 2GX 2015
#NoXML: Eliminating XML in Spring Projects - SpringOne 2GX 2015
 
Freeing Yourself from an RDBMS Architecture
Freeing Yourself from an RDBMS ArchitectureFreeing Yourself from an RDBMS Architecture
Freeing Yourself from an RDBMS Architecture
 
Arquitetando seu aplicativo Android com Jetpack
Arquitetando seu aplicativo Android com JetpackArquitetando seu aplicativo Android com Jetpack
Arquitetando seu aplicativo Android com Jetpack
 
07_UIAndroid.pdf
07_UIAndroid.pdf07_UIAndroid.pdf
07_UIAndroid.pdf
 
Knockout.js
Knockout.jsKnockout.js
Knockout.js
 
Webinar: MongoDB for Content Management
Webinar: MongoDB for Content ManagementWebinar: MongoDB for Content Management
Webinar: MongoDB for Content Management
 

More from Nelson Glauber Leal

More from Nelson Glauber Leal (20)

Seu primeiro app Android e iOS com Compose Multiplatform
Seu primeiro app Android e iOS com Compose MultiplatformSeu primeiro app Android e iOS com Compose Multiplatform
Seu primeiro app Android e iOS com Compose Multiplatform
 
Desenvolvimento Moderno de Aplicações Android 2023
Desenvolvimento Moderno de Aplicações Android 2023Desenvolvimento Moderno de Aplicações Android 2023
Desenvolvimento Moderno de Aplicações Android 2023
 
Novidades incríveis do Android em 2023
Novidades incríveis do Android em 2023Novidades incríveis do Android em 2023
Novidades incríveis do Android em 2023
 
Novidades das Bibliotecas Jetpack do Android (2021)
Novidades das Bibliotecas Jetpack do Android (2021)Novidades das Bibliotecas Jetpack do Android (2021)
Novidades das Bibliotecas Jetpack do Android (2021)
 
Android Jetpack Compose - Turkey 2021
Android Jetpack Compose - Turkey 2021Android Jetpack Compose - Turkey 2021
Android Jetpack Compose - Turkey 2021
 
Jetpack Compose a new way to implement UI on Android
Jetpack Compose a new way to implement UI on AndroidJetpack Compose a new way to implement UI on Android
Jetpack Compose a new way to implement UI on Android
 
Jetpack Compose a nova forma de implementar UI no Android
Jetpack Compose a nova forma de implementar UI no AndroidJetpack Compose a nova forma de implementar UI no Android
Jetpack Compose a nova forma de implementar UI no Android
 
Aplicações assíncronas no Android com
Coroutines & Jetpack
Aplicações assíncronas no Android com
Coroutines & JetpackAplicações assíncronas no Android com
Coroutines & Jetpack
Aplicações assíncronas no Android com
Coroutines & Jetpack
 
Aplicações assíncronas no Android com
Coroutines & Jetpack
Aplicações assíncronas no Android com
Coroutines & JetpackAplicações assíncronas no Android com
Coroutines & Jetpack
Aplicações assíncronas no Android com
Coroutines & Jetpack
 
O que é preciso para ser um desenvolvedor Android
O que é preciso para ser um desenvolvedor AndroidO que é preciso para ser um desenvolvedor Android
O que é preciso para ser um desenvolvedor Android
 
Arquitetando seu app Android com Jetpack
Arquitetando seu app Android com JetpackArquitetando seu app Android com Jetpack
Arquitetando seu app Android com Jetpack
 
Aplicações Assíncronas no Android com Coroutines e Jetpack
Aplicações Assíncronas no Android com Coroutines e JetpackAplicações Assíncronas no Android com Coroutines e Jetpack
Aplicações Assíncronas no Android com Coroutines e Jetpack
 
Mastering Kotlin Standard Library
Mastering Kotlin Standard LibraryMastering Kotlin Standard Library
Mastering Kotlin Standard Library
 
Aplicações assíncronas no Android com Coroutines & Jetpack
Aplicações assíncronas no Android com Coroutines & JetpackAplicações assíncronas no Android com Coroutines & Jetpack
Aplicações assíncronas no Android com Coroutines & Jetpack
 
Introdução ao Desenvolvimento Android com Kotlin
Introdução ao Desenvolvimento Android com KotlinIntrodução ao Desenvolvimento Android com Kotlin
Introdução ao Desenvolvimento Android com Kotlin
 
Persisting Data on SQLite using Room
Persisting Data on SQLite using RoomPersisting Data on SQLite using Room
Persisting Data on SQLite using Room
 
Desenvolvimento Moderno de Aplicativos Android
Desenvolvimento Moderno de Aplicativos AndroidDesenvolvimento Moderno de Aplicativos Android
Desenvolvimento Moderno de Aplicativos Android
 
Desenvolvimento Moderno de aplicativos Android
Desenvolvimento Moderno de aplicativos AndroidDesenvolvimento Moderno de aplicativos Android
Desenvolvimento Moderno de aplicativos Android
 
Turbinando o desenvolvimento Android com Kotlin
Turbinando o desenvolvimento Android com KotlinTurbinando o desenvolvimento Android com Kotlin
Turbinando o desenvolvimento Android com Kotlin
 
Tudo que você precisa saber sobre Constraint Layout
Tudo que você precisa saber sobre Constraint LayoutTudo que você precisa saber sobre Constraint Layout
Tudo que você precisa saber sobre Constraint Layout
 

Recently uploaded

+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
Health
 
AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM TechniquesAI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
VictorSzoltysek
 
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICECHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
9953056974 Low Rate Call Girls In Saket, Delhi NCR
 
TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service provider
mohitmore19
 
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
masabamasaba
 

Recently uploaded (20)

%in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park %in ivory park+277-882-255-28 abortion pills for sale in ivory park
%in ivory park+277-882-255-28 abortion pills for sale in ivory park
 
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
 
%+27788225528 love spells in Vancouver Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Vancouver Psychic Readings, Attraction spells,Br...%+27788225528 love spells in Vancouver Psychic Readings, Attraction spells,Br...
%+27788225528 love spells in Vancouver Psychic Readings, Attraction spells,Br...
 
Generic or specific? Making sensible software design decisions
Generic or specific? Making sensible software design decisionsGeneric or specific? Making sensible software design decisions
Generic or specific? Making sensible software design decisions
 
Right Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsRight Money Management App For Your Financial Goals
Right Money Management App For Your Financial Goals
 
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
+971565801893>>SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHAB...
 
AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM TechniquesAI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
 
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICECHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
 
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
Shapes for Sharing between Graph Data Spaces - and Epistemic Querying of RDF-...
 
%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview
%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview
%in Hazyview+277-882-255-28 abortion pills for sale in Hazyview
 
Define the academic and professional writing..pdf
Define the academic and professional writing..pdfDefine the academic and professional writing..pdf
Define the academic and professional writing..pdf
 
VTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learnVTU technical seminar 8Th Sem on Scikit-learn
VTU technical seminar 8Th Sem on Scikit-learn
 
The Top App Development Trends Shaping the Industry in 2024-25 .pdf
The Top App Development Trends Shaping the Industry in 2024-25 .pdfThe Top App Development Trends Shaping the Industry in 2024-25 .pdf
The Top App Development Trends Shaping the Industry in 2024-25 .pdf
 
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
%in Bahrain+277-882-255-28 abortion pills for sale in Bahrain
 
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
 
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
 
%in Harare+277-882-255-28 abortion pills for sale in Harare
%in Harare+277-882-255-28 abortion pills for sale in Harare%in Harare+277-882-255-28 abortion pills for sale in Harare
%in Harare+277-882-255-28 abortion pills for sale in Harare
 
TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service provider
 
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa%in tembisa+277-882-255-28 abortion pills for sale in tembisa
%in tembisa+277-882-255-28 abortion pills for sale in tembisa
 
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
%+27788225528 love spells in Colorado Springs Psychic Readings, Attraction sp...
 

Dominando o Data Binding no Android

  • 1. Dominando o Data Binding
 no Android +Nelson Glauber @nglauber www.nglauber.com.br
  • 3. Por que Data Binding?
  • 4.
  • 5. Data Binding • Facilita a ligação entre Model e View • Estende os arquivos de layout com micro-expressões • Binders customizados reduzem a repetição de código • Tratamento de NPE
  • 7. public class Book { private String id; private String title; private String author; private String coverUrl; private int pages; private int year; private Publisher publisher; private boolean available; private MediaType mediaType; private float rating; // Getters and setters... }
  • 8. Book book = (Book)getIntent().getSerializableExtra(EXTRA_LIVRO); ImageView imgCover = (ImageView) findViewById(R.id.image_cover); TextView txtTitle = (TextView) findViewById(R.id.text_title); TextView txtAuthor = (TextView) findViewById(R.id.text_author); TextView txtPages = (TextView) findViewById(R.id.text_pages); TextView txtYear = (TextView) findViewById(R.id.text_year); TextView txtPublisher = (TextView) findViewById(R.id.text_publisher); TextView txtAvailable = (TextView) findViewById(R.id.text_available); TextView txtMediaType = (TextView) findViewById(R.id.text_media_type); RatingBar ratingBook = (RatingBar) findViewById(R.id.rating_book); Glide.with(this).load(book.getCoverUrl()).into(imgCover); txtTitle.setText(book.getTitle()); txtAuthor.setText(book.getAuthor()); txtPages.setText(getString(R.string.text_format_book_pages, book.getPages())); txtYear.setText(getString(R.string.text_format_book_year, book.getYear())); txtPublisher.setText(book.getPublisher().getName()); txtAvailable.setText(book.isAvailable() ? R.string.text_book_available : R.string.text_book_unavailable); txtMediaType.setText(book.getMediaType().toString()); ratingBook.setNumStars(book.getRating());
  • 10. Book book = (Book)getIntent().getSerializableExtra(EXTRA_BOOK); ActivityDetailViewBinding mBinding =
 DataBindingUtil.setContentView(this, R.layout.activity_detail_view); mBinding.setBook(book);
  • 15. public class MainActivity extends AppCompatActivity { ActivityMainBinding mBinding; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mBinding = DataBindingUtil.setContentView(this, R.layout.activity_main); mBinding.textViewName.setText(“DataBinding is cool!!!”); } } MainActivity.java camelCase
  • 16.
  • 17. Se não gostar do nome da classe… MainActivity.java res/layout/activity_main.xml <layout ...> <data class="VaiFilhaoBinding"> ... </data> public class MainActivity extends AppCompatActivity { VaiFilhaoBinding binding; ...
  • 19.
  • 20. Book book = (Book)getIntent().getSerializableExtra(EXTRA_LIVRO); ImageView imgCover = (ImageView) findViewById(R.id.image_cover); TextView txtTitle = (TextView) findViewById(R.id.text_title); TextView txtAuthor = (TextView) findViewById(R.id.text_author); TextView txtPages = (TextView) findViewById(R.id.text_pages); TextView txtYear = (TextView) findViewById(R.id.text_year); TextView txtPublisher = (TextView) findViewById(R.id.text_publisher); TextView txtAvailable = (TextView) findViewById(R.id.text_available); TextView txtMediaType = (TextView) findViewById(R.id.text_media_type); RatingBar ratingBook = (RatingBar) findViewById(R.id.rating_book); Glide.with(this).load(book.getCoverUrl()).into(imgCover); txtTitle.setText(book.getTitle()); txtAuthor.setText(book.getAuthor()); txtPages.setText(getString(R.string.text_format_book_pages, book.getPages())); txtYear.setText(getString(R.string.text_format_book_year, book.getYear())); txtPublisher.setText(book.getPublisher().getName()); txtAvailable.setText(book.isAvailable() ? R.string.text_book_available : R.string.text_book_unavailable); txtMediaType.setText(book.getMediaType().toString()); ratingBook.setNumStars(book.getRating());
  • 21. Book book = (Book)getIntent().getSerializableExtra(EXTRA_BOOK); ActivityDetailViewBinding mBinding =
 DataBindingUtil.setContentView(this, R.layout.activity_detail_view); mBinding.setBook(book);
  • 22. <layout xmlns:android="http://schemas.android.com/apk/res/android" ...> <data> <variable name="book" type="br.com.nglauber.livrosfirebase.model.Book" /> </data> <LinearLayout ... > <ImageView android:src="@{book.coverUrl}" ... /> <TextView android:text="@{book.title}" ... /> <TextView android:text="@{book.author}" ... /> <TextView android:text="@{@string/text_format_book_pages(book.pages)}" ... /> <TextView android:text="@{@string/text_format_book_year(book.year)}" ... /> <TextView android:text="@{book.publisher.name}" ... /> <TextView android:text="@{book.available ? @string/text_book_available : @string/text_book_unavailable}" ... /> <TextView android:text="@{book.mediaType}" ... /> <RatingBar android:rating="@{book.rating}" ... /> </LinearLayout> </layout>
  • 23. <layout xmlns:android="http://schemas.android.com/apk/res/android" ...> <data> <variable name="book" type="br.com.nglauber.livrosfirebase.model.Book" /> </data> <LinearLayout ... > <ImageView android:src="@{book.coverUrl}" ... /> <TextView android:text="@{book.title}" ... /> <TextView android:text="@{book.author}" ... /> <TextView android:text="@{@string/text_format_book_pages(book.pages)}" ... /> <TextView android:text="@{@string/text_format_book_year(book.year)}" ... /> <TextView android:text="@{book.publisher.name}" ... /> <TextView android:text="@{book.available ? @string/text_book_available : @string/text_book_unavailable}" ... /> <TextView android:text="@{book.mediaType}" ... /> <RatingBar android:progress="@{book.rating}" ... /> </LinearLayout> </layout> <!-- strings.xml --> <string name="text_format_book_pages">Número de páginas: %1$d</string> <string name="text_format_book_year">Ano de publicação: %1$d</string>
  • 24. <layout xmlns:android="http://schemas.android.com/apk/res/android" ...> <data> <variable name="book" type="br.com.nglauber.livrosfirebase.model.Book" /> </data> <LinearLayout ... > <ImageView android:src="@{book.coverUrl}" ... /> <TextView android:text="@{book.title}" ... /> <TextView android:text="@{book.author}" ... /> <TextView android:text="@{@string/text_format_book_pages(book.pages)}" ... /> <TextView android:text="@{@string/text_format_book_year(book.year)}" ... /> <TextView android:text="@{book.publisher.name}" ... /> <TextView android:text="@{book.available ? @string/text_book_available : @string/text_book_unavailable}" ... /> <TextView android:text="@{book.mediaType}" ... /> <RatingBar android:progress="@{book.rating}" ... /> </LinearLayout> </layout>
  • 26. NÃO!
  • 27. <layout xmlns:android="http://schemas.android.com/apk/res/android" ...> <data> <variable name="book" type="br.com.nglauber.livrosfirebase.model.Book" /> </data> <LinearLayout ... > <ImageView android:src="@{book.coverUrl}" ... /> <TextView android:text="@{book.title}" ... /> <TextView android:text="@{book.author}" ... /> <TextView android:text="@{@string/text_format_book_pages(book.pages)}" ... /> <TextView android:text="@{@string/text_format_book_year(book.year)}" ... /> <TextView android:text="@{book.publisher.name}" ... /> <TextView android:text="@{book.available ? @string/text_book_available : @string/text_book_unavailable}" ... /> <TextView android:text="@{book.mediaType}" ... /> <RatingBar android:progress="@{book.rating}" ... /> </LinearLayout> </layout> public class Book { ... private String coverUrl; private MediaType mediaType; }
  • 29. public class TextBinding { @BindingAdapter({"android:text"}) public static void setMediaTypeText(TextView textView, MediaType mediaType){ Context context = textView.getContext(); switch (mediaType) { case EBOOK: textView.setText(context.getString(R.string.text_book_media_ebook)); break; case PAPER: textView.setText(context.getString(R.string.text_book_media_paper)); break; default: textView.setText(null); } } } TextBinding.java
  • 30. public class ImageBinding { @BindingAdapter({"android:src"}) public static void setImageUrl(ImageView imageView, String url){ Glide.with(imageView.getContext()) .load(url) .into(imageView); } @BindingAdapter({"android:src", "placeHolder"}) public static void setImageUrl(ImageView imageView, String url, Drawable placeholder){ Glide.with(imageView.getContext()) .load(url) .placeholder(placeholder) .into(imageView); } } ImageBinding.java
  • 32.
  • 34.
  • 35. BookFragment.java private FragmentBookBinding mBinding; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { mBinding = DataBindingUtil.inflate(inflater, R.layout.fragment_book, container, false); ... return mBinding.getRoot(); }
  • 36. res/layout/item_book.xml <layout ...> <data> <variable name="book" type="br.com.nglauber.livrosfirebase.model.Book"/> </data> <android.support.v7.widget.CardView ...> <RelativeLayout ...> <ImageView android:src="@{book.coverUrl}" ... /> <TextView android:text="@{book.title}" ... /> <TextView android:text="@{book.author}" ... /> </RelativeLayout> </android.support.v7.widget.CardView> </layout>
  • 37. BookViewHolder.java public static class BookViewHolder extends RecyclerView.ViewHolder { ItemBookBinding binding; public BookViewHolder(ItemBookBinding binding) { super(binding.getRoot()); this.binding = binding; } }
  • 38. @Override public BookViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { ItemBookBinding binding = DataBindingUtil.inflate( LayoutInflater.from(parent.getContext()), R.layout.item_book, parent, false); final BookViewHolder vh = new BookViewHolder(binding); vh.itemView.setOnClickListener(...); return vh; } @Override public void onBindViewHolder(BookViewHolder holder, int pos) { Book book = mBooksList.get(pos); holder.binding.setBook(book); holder.binding.executePendingBindings(); } BookAdapter.java
  • 39.
  • 40. E se os dados mudarem?
  • 41. public class Book extends BaseObservable { // Atributos... @Bindable public String getTitle() { return title; } public void setTitle(String title) { this.title = title; notifyPropertyChanged(BR.title); } @Bindable public String getAuthor() { return author; } public void setAuthor(String author) { this.author = author; notifyPropertyChanged(BR.author); } // Demais getters/setters Book.java
  • 42. public class Book implements Observable { // Copie as coisas do BaseObservable :) }
  • 43. public class BaseObservable implements Observable { private transient PropertyChangeRegistry mCallbacks; public BaseObservable() { } @Override public synchronized void addOnPropertyChangedCallback(OnPropertyChangedCallback callback) { if (mCallbacks == null) { mCallbacks = new PropertyChangeRegistry(); } mCallbacks.add(callback); } @Override public synchronized void removeOnPropertyChangedCallback(OnPropertyChangedCallback callback) { if (mCallbacks != null) { mCallbacks.remove(callback); } } public synchronized void notifyChange() { if (mCallbacks != null) { mCallbacks.notifyCallbacks(this, 0, null); } } public void notifyPropertyChanged(int fieldId) { if (mCallbacks != null) { mCallbacks.notifyCallbacks(this, fieldId, null); } } }
  • 44. import android.databinding.ObservableBoolean; import android.databinding.ObservableField; import android.databinding.ObservableInt; public class Book { //... private final ObservableField<String> title; private final ObservableInt year; private final ObservableBoolean available; public Book() { //... this.title = new ObservableField<>(); this.year = new ObservableInt(2016); this.available = new ObservableBoolean(false); } public ObservableField<String> getTitle() { return title; } public void setTitle(String title) { this.title.set(title); } public ObservableInt getYear() { return year; } public void setYear(double year) { this.year.set(year); } public ObservableBoolean isAvailable() { return available; } public void setAvailable(boolean available) { this.available.set(available); } }
  • 46. <layout ...> <data> <variable name="texto" type="String"/> </data> <LinearLayout ... > <TextView ... android:id="@+id/textViewNome" android:text="@{texto}" /> <EditText ... android:id="@+id/editTextNome" android:text="@={texto}"/> </LinearLayout> </layout>
  • 47.
  • 48. <layout ...> <data> ... <import type="br.com.nglauber.livrosfirebase.model.MediaType" /> <variable name="book" type="br.com.nglauber.livrosfirebase.model.Book" /> </data> <LinearLayout ...> <ImageView android:src="@{book.coverUrl}" ... /> <EditText android:text="@={book.title}" ... /> <EditText android:text="@={book.author}" ... /> <EditText android:text="@={book.pages}" ... /> <EditText android:text="@={book.year}" ... /> <Spinner ...> <!-- trataremos desse em breve. --> <CheckBox android:checked="@={book.available}" ... /> <RadioGroup ...> <RadioButton ... android:checked="@{book.mediaTypeValue == MediaType.EBOOK}" ... /> <RadioButton ... android:checked="@{book.mediaTypeValue == MediaType.PAPER}" ... /> </RadioGroup> <RatingBar android:rating="@={book.rating}" ... /> ... </LinearLayout> </layout>
  • 49. <layout ...> <data> ... <import type="br.com.nglauber.livrosfirebase.model.MediaType" /> <variable name="book" type="br.com.nglauber.livrosfirebase.model.Book" /> </data> <LinearLayout ...> <ImageView android:src="@{book.coverUrl}" ... /> <EditText android:text="@={book.title}" ... /> <EditText android:text="@={book.author}" ... /> <EditText android:text="@={book.pages}" ... /> <EditText android:text="@={book.year}" ... /> <Spinner ...> <!-- trataremos desse em breve. --> <CheckBox android:checked="@={book.available}" ... /> <RadioGroup ...> <RadioButton ... android:checked="@{book.mediaTypeValue == MediaType.EBOOK}" ... /> <RadioButton ... android:checked="@{book.mediaTypeValue == MediaType.PAPER}" ... /> </RadioGroup> <RatingBar android:progress="@={book.rating}" ... /> ... </LinearLayout> </layout>
  • 51. Cuidado com loops! EditText
 android:text="@={book.title}" public class Book extends BaseObservable { // Atributos... @Bindable public String getTitle() { return title; } public void setTitle(String title) { this.title = title; notifyPropertyChanged(BR.title); } // Demais getters/setters
  • 52. public class EditTextBindingAdapters { @InverseBindingAdapter(attribute = "android:text") public static int getTextAsInt(EditText editText) { try { return Integer.parseInt(editText.getText().toString()); } catch (Exception e){ return 0; } } @BindingAdapter({"android:text"}) public static void setTextFromInt(EditText editText, int value){ if (getTextAsInt(editText) != value) { editText.setText(String.valueOf(value)); } } } EditTextBindingAdapters.java
  • 54. <layout ...> <data> ... <variable name="presenter" type=“br.com.nglauber.livrosfirebase.DetailEditActivity"/> </data> <LinearLayout ...> ... <TextView ... android:onLongClick="@{presenter::longClick}" /> <Button ... android:onClick=“@{presenter::clickSaveBook}”/> <EditText ... android:onFocusChange="@{presenter::focusChanged}"/> </LinearLayout> </layout> res/layout/activity_detail_edit.xml
  • 55. @Override protected void onCreate(Bundle savedInstanceState) { ... binding.setBook(book); binding.setPresenter(this); } public void clickSaveBook(View view) { Toast.makeText(this, book.toString(), Toast.LENGTH_SHORT).show(); } public boolean longClick(View view){ book.setRating(book.getRating() + 1); return true; } public void focusChanged(View v, boolean focus){ if (!focus) showProduct(v); } DetailEditActivity.java Respeite a assinatura do método
  • 56. <layout ...> <data> <import type="br.com.nglauber.livrosfirebase.model.MediaType" /> ... <variable name="presenter" type="br.com.nglauber.livrosfirebase.DetailEditActivity" /> </data> <LinearLayout ...> ... <RadioGroup ...> <RadioButton ... android:checked="@{book.mediaTypeValue == MediaType.EBOOK}" android:onCheckedChanged="@{presenter::onMediaTypeChanged}" /> <RadioButton ... android:checked="@{book.mediaTypeValue == MediaType.PAPER}" android:onCheckedChanged="@{presenter::onMediaTypeChanged}" /> </RadioGroup> ... </LinearLayout> </layout>
  • 57. public void onMediaTypeChanged(CompoundButton buttonView, boolean isChecked) { if (isChecked) { if (buttonView == mBinding.radioMediaEbook) { mBinding.getBook().setMediaTypeValue(MediaType.EBOOK); } else if (buttonView == mBinding.radioMediaPaper) { mBinding.getBook().setMediaTypeValue(MediaType.PAPER); } } }
  • 58. public class Publisher { private String id; private String name; public String getId() { return id; } public void setId(String id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } @Override public String toString() { return name; } } public class Book extends BaseObservable { private Publisher publisher; ... @Bindable public Publisher getPublisher() { return publisher; } public void setPublisher(Publisher publisher) { this.publisher = publisher; notifyPropertyChanged(BR.publisher); } }
  • 59. <layout ...> <data> <import type="java.util.List"/> <variable name="book" type="br.com.nglauber.livrosfirebase.model.Book" /> <variable name="presenter" type="br.com.nglauber.livrosfirebase.DetailEditActivity" /> <variable name="publishers" type="java.util.List&lt;br.com.nglauber.livrosfirebase.model.Publisher&gt;" /> </data>
 <LinearLayout ...> <Spinner ... android:entries="@{publishers}" android:selection="@{publishers.indexOf(book.publisher)}" android:onItemSelected="@{(p, v, pos, id)->book.setPublisher(publishers[pos])}" /> </LinearLayout> </layout>
  • 60. DetailEditActivity.java ObservableList<Publisher> publishers = loadListFromSomewhere(); mBinding.setPublishers(publishers);
  • 65. https://github.com/lisawray/fontbinding public class TextViewBinderAdapter { @BindingAdapter({"font"}) public static void setFont(TextView textView,String font){ AssetManager assets = textView.getContext().getAssets(); Typeface typeface = Typeface.createFromAsset(assets, font); textView.setTypeface(typeface); } } <TextView app:font="@{`FunnyKid.ttf`}" .../>
  • 66. Mas se tiver um “set” pode usar! <android.support.v4.widget.DrawerLayout ... app:scrimColor="@{@color/scrim}" app:drawerListener="@{fragment.drawerListener}"/>
  • 68. Expression Language <TextView ... android:text="@{user.displayName ?? user.lastName}"/> <TextView ... android:text="@{`User: ` + user.name}”/> <LinearLayout ... android:padding="@{large? @dimen/largePadding : @dimen/smallPadding}"/>
  • 69. res/values/colors.xml <color name="red">#F00</color> <color name="black">#000</color> <TextView ... android:id="@+id/text_title" android:textColor="@{book.available ? @color/black : @color/red}" android:text="@{book.title}" />
  • 70. res/values/strings.xml <string name="price_format">$ %1$.2f</string> <TextView ... android:id="@+id/text_price" android:text="@{@string/price_format(book.price)}" /> getString(R.string.price_format, product.price);
  • 71. Include <layout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"> <data> <variable name="book" type=“...Book”/> <variable name=“presenter" type=“...DetailEditActivity" /> </data> <LinearLayout ...> <include android:id="@+id/content" layout="@layout/content_detail_edit" app:presenter="@{presenter}" app:book="@{book}" /> </LinearLayout> </layout>
  • 72. Include ActivityDetailEditBinding mBinding = DataBindingUtil.setContentView(this, R.layout.activity_detail_edit); mBinding.setBook(book); mBinding.setPresenter(this); mBinding.content.setPublishers(new ObservableArrayList<Publisher>());
  • 73. Expression Chain <layout ...> <data> <import type="android.view.View" /> ... </data> <LinearLayout ...> <ImageView ... android:id="@+id/image_cover" android:visibility="@{book.available ? View.VISIBLE : View.INVISIBLE}" /> <RadioGroup ... android:id="@+id/radio_group_media_type" android:visibility="@{imageCover.visibility}" /> <RatingBar android:visibility="@{radioGroupMediaType.visibility}" android:id=“@+id/rating_book"> <CheckBox ... android:id="@+id/check_available" android:checked="@={book.available}" />
  • 74. Ouvindo coisas… :) binding.addOnPropertyChangedCallback(new Observable.OnPropertyChangedCallback() { @Override public void onPropertyChanged(Observable observable, int i) { if (i == br.com.nglauber.uidemo.BR.name){ Product p = (Product)observable; Log.d("NGVL", p.getName()); } } });
  • 75. Ouvindo coisas… :) Use para animações binding.addOnRebindCallback(new OnRebindCallback() { @Override public boolean onPreBind(ViewDataBinding binding) { return super.onPreBind(binding); } @Override public void onCanceled(ViewDataBinding binding) { super.onCanceled(binding); } @Override public void onBound(ViewDataBinding binding) { super.onBound(binding); } });
  • 76. Aplicando no seu projeto 1. Remova os findViewById’s :) 2. Faça o Binding dos seus objetos. 3. Use os callbacks (eventos) de UI. 4. Aproveite os objetos observáveis. 5. Two-way Data Binding é vida! ♥
  • 77. Boas práticas • Não coloque lógica de negócios na tela. Apenas lógica de tela. • Os eventos disparados executarão na UI Thread. • Simplifique a lógica de UI (não coloque expressões complicadas, crie métodos para isso. • Considere utilizar um ViewModel. • Leve os BinderAdapters com você :) Você só vai precisar escrevê- los uma vez. // TODO: Fazer uma lib para isso :p
  • 78. Referências • Data Binding -- Write Apps Faster (Android Dev Summit 2015)
 https://www.youtube.com/watch?v=NBbeQMOcnZ0 • Data Binding Documentation (pode melhorar né…?)
 http://developer.android.com/tools/data-binding/guide.html • Nelson Glauber Blog
 http://www.nglauber.com.br/2016/05/android-data-binding.html • Advanced Data Binding (Google I/O 2016)
 https://www.youtube.com/watch?v=DAmMN7m3wLU