SlideShare a Scribd company logo
Dominando o Data Binding

no Android
+Nelson Glauber
@nglauber
www.nglauber.com.br
@nglauber
+NelsonGlauber
www.nglauber.com.br
Por que Data Binding?
Dominando o Data Binding no Android
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
Não tem passo 2 o/
android {
...
dataBinding {
enabled true
}
}
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
Dominando o Data Binding no Android
Se não gostar do nome da classe…
MainActivity.java
res/layout/activity_main.xml
<layout ...>
<data class="AwsomeBinding">
...
</data>
public class MainActivity extends AppCompatActivity {
AwsomeBinding 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.mediaTypeValue}" ... />
<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.mediaTypeValue}" ... />
<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.mediaTypeValue}" ... />
<RatingBar android:progress="@{book.rating}" ... />
</LinearLayout>
</layout>
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
<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"/>
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
Dominando o Data Binding no Android
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 {
private PropertyChangeRegistry mCallbacks;
// Copia 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); }
}
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
Dominando o Data Binding no Android
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>
Dominando o Data Binding no Android
<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

PDF
Dominando o Data Binding no Android
PPTX
J Query (Complete Course) by Muhammad Ehtisham Siddiqui
PDF
"Android Data Binding в массы" Михаил Анохин
PDF
Михаил Анохин "Data binding 2.0"
PDF
Getting Started with Combine And SwiftUI
PDF
Angular를 활용한 웹 프론트단 개발과 2.0에서 달라진점
PDF
Client Side MVC & Angular
PDF
Bootstrap과 UI-Bootstrap
Dominando o Data Binding no Android
J Query (Complete Course) by Muhammad Ehtisham Siddiqui
"Android Data Binding в массы" Михаил Анохин
Михаил Анохин "Data binding 2.0"
Getting Started with Combine And SwiftUI
Angular를 활용한 웹 프론트단 개발과 2.0에서 달라진점
Client Side MVC & Angular
Bootstrap과 UI-Bootstrap

What's hot (20)

PDF
Responsive mobile design
PDF
[FEConf Korea 2017]Angular 컴포넌트 대화법
PDF
22 j query1
PDF
Responsive mobile design in practice
PDF
SwiftUI and Combine All the Things
PPTX
AngularJs Superheroic JavaScript MVW Framework Services by Miracle Studios
PPTX
Jquery Complete Presentation along with Javascript Basics
PDF
Guia de Sobrevivência JS no mundo Open Source
PDF
前端MVC之BackboneJS
PDF
MVVM with SwiftUI and Combine
PDF
React 소개 및 구현방법 Demo
PDF
Building iPhone Web Apps using "classic" Domino
PDF
jQuery for beginners
PDF
Django workshop : let's make a blog
PPTX
jQuery Presentation
PPT
Jquery ui
PDF
AngularJS: an introduction
PPTX
A Novel Approach to Scraping Websites - Rob Ousbey, MozCon 2020
PPTX
Dom selecting & jQuery
DOCX
Angular js
Responsive mobile design
[FEConf Korea 2017]Angular 컴포넌트 대화법
22 j query1
Responsive mobile design in practice
SwiftUI and Combine All the Things
AngularJs Superheroic JavaScript MVW Framework Services by Miracle Studios
Jquery Complete Presentation along with Javascript Basics
Guia de Sobrevivência JS no mundo Open Source
前端MVC之BackboneJS
MVVM with SwiftUI and Combine
React 소개 및 구현방법 Demo
Building iPhone Web Apps using "classic" Domino
jQuery for beginners
Django workshop : let's make a blog
jQuery Presentation
Jquery ui
AngularJS: an introduction
A Novel Approach to Scraping Websites - Rob Ousbey, MozCon 2020
Dom selecting & jQuery
Angular js
Ad

Viewers also liked (20)

PDF
Deep dive into Android Data Binding
PDF
Android Wear DevFest Sudeste 2015
PDF
Google Play Services Rocks!!!
PDF
Android Libs - AndroidDevConf
PDF
Android FREETEC
PDF
Aumentando a produtividade com Android Libs
PDF
Android Wear Androidos 2015
PPTX
Android data binding
PDF
Conhecendo o Android Wear
PDF
MVVM & Data Binding Library
PDF
Android Data Binding in action using MVVM pattern - droidconUK
PDF
MVVM with DataBinding on android
PDF
Android DevConference - Data Binding: Código limpo, manutenção garantida
PPTX
Data binding
PDF
Android L e Android Wear
PDF
Android e iOS: Por que eles são diferentes... ou não.
PDF
Android Lollipop + Android Wear
PDF
Android Wear
PDF
Android Databinding Library
PDF
Testable Android Apps using data binding and MVVM
Deep dive into Android Data Binding
Android Wear DevFest Sudeste 2015
Google Play Services Rocks!!!
Android Libs - AndroidDevConf
Android FREETEC
Aumentando a produtividade com Android Libs
Android Wear Androidos 2015
Android data binding
Conhecendo o Android Wear
MVVM & Data Binding Library
Android Data Binding in action using MVVM pattern - droidconUK
MVVM with DataBinding on android
Android DevConference - Data Binding: Código limpo, manutenção garantida
Data binding
Android L e Android Wear
Android e iOS: Por que eles são diferentes... ou não.
Android Lollipop + Android Wear
Android Wear
Android Databinding Library
Testable Android Apps using data binding and MVVM
Ad

Similar to Dominando o Data Binding no Android (14)

PDF
Arquitetando seu app Android com Jetpack
PDF
How to use data binding in android
PDF
Arquitetando seu aplicativo Android com Jetpack
PPTX
Data Binding: Is It the Next Big Thing?
PPTX
Data binding в массы! (1.2)
PDF
Data binding w Androidzie
PDF
Android Design Patterns
PDF
Infinum Android Talks #14 - Data binding to the rescue... or not (?) by Krist...
PDF
Data binding в массы!
PPTX
Android data bind
PDF
Infinum android talks #12 - Google IO report: Milkshakes, Marshmallows and Ma...
PDF
RIBs - Fragments which work
PDF
SE2016 Android Mikle Anokhin "Speed up application development with data bind...
PDF
Effective Android Data Binding
Arquitetando seu app Android com Jetpack
How to use data binding in android
Arquitetando seu aplicativo Android com Jetpack
Data Binding: Is It the Next Big Thing?
Data binding в массы! (1.2)
Data binding w Androidzie
Android Design Patterns
Infinum Android Talks #14 - Data binding to the rescue... or not (?) by Krist...
Data binding в массы!
Android data bind
Infinum android talks #12 - Google IO report: Milkshakes, Marshmallows and Ma...
RIBs - Fragments which work
SE2016 Android Mikle Anokhin "Speed up application development with data bind...
Effective Android Data Binding

More from Nelson Glauber Leal (20)

PDF
Insights no desenvolvimento Android para 2024
PDF
Seu primeiro app Android e iOS com Compose Multiplatform
PDF
Desenvolvimento Moderno de Aplicações Android 2023
PDF
Novidades incríveis do Android em 2023
PDF
Novidades das Bibliotecas Jetpack do Android (2021)
PDF
Android Jetpack Compose - Turkey 2021
PDF
Jetpack Compose a new way to implement UI on Android
PDF
Jetpack Compose a nova forma de implementar UI no Android
PDF
Aplicações assíncronas no Android com
Coroutines & Jetpack
PDF
Aplicações assíncronas no Android com
Coroutines & Jetpack
PDF
O que é preciso para ser um desenvolvedor Android
PDF
Arquitetando seu app Android com Jetpack
PDF
Aplicações Assíncronas no Android com Coroutines e Jetpack
PDF
Mastering Kotlin Standard Library
PDF
Aplicações assíncronas no Android com Coroutines & Jetpack
PDF
Introdução ao Desenvolvimento Android com Kotlin
PDF
Persisting Data on SQLite using Room
PDF
Desenvolvimento Moderno de Aplicativos Android
PDF
Desenvolvimento Moderno de aplicativos Android
PDF
Turbinando o desenvolvimento Android com Kotlin
Insights no desenvolvimento Android para 2024
Seu primeiro app Android e iOS com Compose Multiplatform
Desenvolvimento Moderno de Aplicações Android 2023
Novidades incríveis do Android em 2023
Novidades das Bibliotecas Jetpack do Android (2021)
Android Jetpack Compose - Turkey 2021
Jetpack Compose a new way to implement UI on 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 & Jetpack
O que é preciso para ser um desenvolvedor Android
Arquitetando seu app Android com Jetpack
Aplicações Assíncronas no Android com Coroutines e Jetpack
Mastering Kotlin Standard Library
Aplicações assíncronas no Android com Coroutines & Jetpack
Introdução ao Desenvolvimento Android com Kotlin
Persisting Data on SQLite using Room
Desenvolvimento Moderno de Aplicativos Android
Desenvolvimento Moderno de aplicativos Android
Turbinando o desenvolvimento Android com Kotlin

Recently uploaded (20)

PDF
Agricultural_Statistics_at_a_Glance_2022_0.pdf
PDF
Network Security Unit 5.pdf for BCA BBA.
PDF
Per capita expenditure prediction using model stacking based on satellite ima...
PDF
Dropbox Q2 2025 Financial Results & Investor Presentation
PDF
Mobile App Security Testing_ A Comprehensive Guide.pdf
PPTX
Understanding_Digital_Forensics_Presentation.pptx
DOCX
The AUB Centre for AI in Media Proposal.docx
PPTX
sap open course for s4hana steps from ECC to s4
PDF
Spectral efficient network and resource selection model in 5G networks
PDF
MIND Revenue Release Quarter 2 2025 Press Release
PPTX
Detection-First SIEM: Rule Types, Dashboards, and Threat-Informed Strategy
PDF
Architecting across the Boundaries of two Complex Domains - Healthcare & Tech...
PPT
“AI and Expert System Decision Support & Business Intelligence Systems”
PDF
NewMind AI Weekly Chronicles - August'25 Week I
PPTX
Spectroscopy.pptx food analysis technology
PPTX
Digital-Transformation-Roadmap-for-Companies.pptx
PDF
TokAI - TikTok AI Agent : The First AI Application That Analyzes 10,000+ Vira...
PDF
Unlocking AI with Model Context Protocol (MCP)
PDF
Empathic Computing: Creating Shared Understanding
PPTX
Big Data Technologies - Introduction.pptx
Agricultural_Statistics_at_a_Glance_2022_0.pdf
Network Security Unit 5.pdf for BCA BBA.
Per capita expenditure prediction using model stacking based on satellite ima...
Dropbox Q2 2025 Financial Results & Investor Presentation
Mobile App Security Testing_ A Comprehensive Guide.pdf
Understanding_Digital_Forensics_Presentation.pptx
The AUB Centre for AI in Media Proposal.docx
sap open course for s4hana steps from ECC to s4
Spectral efficient network and resource selection model in 5G networks
MIND Revenue Release Quarter 2 2025 Press Release
Detection-First SIEM: Rule Types, Dashboards, and Threat-Informed Strategy
Architecting across the Boundaries of two Complex Domains - Healthcare & Tech...
“AI and Expert System Decision Support & Business Intelligence Systems”
NewMind AI Weekly Chronicles - August'25 Week I
Spectroscopy.pptx food analysis technology
Digital-Transformation-Roadmap-for-Companies.pptx
TokAI - TikTok AI Agent : The First AI Application That Analyzes 10,000+ Vira...
Unlocking AI with Model Context Protocol (MCP)
Empathic Computing: Creating Shared Understanding
Big Data Technologies - Introduction.pptx

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?
  • 6. 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... }
  • 7. 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());
  • 9. Book book = (Book)getIntent().getSerializableExtra(EXTRA_BOOK); ActivityDetailViewBinding mBinding =
 DataBindingUtil.setContentView(this, R.layout.activity_detail_view); mBinding.setBook(book);
  • 11. Configuração Passo 1 Não tem passo 2 o/ android { ... dataBinding { enabled true } }
  • 13. 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
  • 15. Se não gostar do nome da classe… MainActivity.java res/layout/activity_main.xml <layout ...> <data class="AwsomeBinding"> ... </data> public class MainActivity extends AppCompatActivity { AwsomeBinding binding; ...
  • 17. 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());
  • 18. Book book = (Book)getIntent().getSerializableExtra(EXTRA_BOOK); ActivityDetailViewBinding mBinding =
 DataBindingUtil.setContentView(this, R.layout.activity_detail_view); mBinding.setBook(book);
  • 19. <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.mediaTypeValue}" ... /> <RatingBar android:rating="@{book.rating}" ... /> </LinearLayout> </layout>
  • 20. <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.mediaTypeValue}" ... /> <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>
  • 21. <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>
  • 23. NÃO!
  • 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.mediaTypeValue}" ... /> <RatingBar android:progress="@{book.rating}" ... /> </LinearLayout> </layout>
  • 26. 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
  • 28. 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
  • 30. E se os dados mudarem?
  • 31. 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
  • 32. public class Book implements Observable { private PropertyChangeRegistry mCallbacks; // Copia as coisas do BaseObservable :) }
  • 33. 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); } } }
  • 34. 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); } }
  • 36. 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(); }
  • 37. 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>
  • 38. BookViewHolder.java public static class BookViewHolder extends RecyclerView.ViewHolder { ItemBookBinding binding; public BookViewHolder(ItemBookBinding binding) { super(binding.getRoot()); this.binding = binding; } }
  • 39. @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
  • 42. <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>
  • 44. <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>
  • 45. <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>
  • 47. 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
  • 48. 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
  • 50. <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
  • 51. @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
  • 52. <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>
  • 53. 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); } } }
  • 54. 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); } }
  • 55. <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>
  • 56. DetailEditActivity.java ObservableList<Publisher> publishers = loadListFromSomewhere(); mBinding.setPublishers(publishers);
  • 61. 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`}" .../>
  • 62. Mas se tiver um “set” pode usar! <android.support.v4.widget.DrawerLayout ... app:scrimColor="@{@color/scrim}" app:drawerListener="@{fragment.drawerListener}"/>
  • 64. Expression Language <TextView ... android:text="@{user.displayName ?? user.lastName}"/> <TextView ... android:text="@{`User: ` + user.name}”/> <LinearLayout ... android:padding="@{large? @dimen/largePadding : @dimen/smallPadding}"/>
  • 65. 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}" />
  • 66. 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);
  • 67. 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>
  • 68. Include ActivityDetailEditBinding mBinding = DataBindingUtil.setContentView(this, R.layout.activity_detail_edit); mBinding.setBook(book); mBinding.setPresenter(this); mBinding.content.setPublishers(new ObservableArrayList<Publisher>());
  • 69. 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}" />
  • 70. 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()); } } });
  • 71. 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); } });
  • 72. 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! ♥
  • 73. 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
  • 74. 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