SlideShare uma empresa Scribd logo
1 de 79
Baixar para ler offline
Android Data Binding in action
using MVVM pattern
Fabio Collini
2
Ego slide
@fabioCollini
linkedin.com/in/fabiocollini
github.com/fabioCollini
medium.com/@fabioCollini
codingjam.it
3
Agenda
1. Data Binding basics
2. Custom attributes
3. Components
4. Two Way Data Binding
5. Model View ViewModel
4
Example project
5
match_result.xml
<?xml version="1.0" encoding="utf-8"?>

<LinearLayout style="@style/root_layout"

xmlns:android=“http://schemas.android.com/apk/res/android">


<ImageView android:id="@+id/result_gif" style="@style/gif"/>



<LinearLayout style="@style/team_layout">

<TextView android:id="@+id/home_team" style="@style/name"/>

<TextView android:id="@+id/home_goals" style="@style/goals"/>

</LinearLayout>



<LinearLayout style="@style/team_layout">

<TextView android:id="@+id/away_team" style="@style/name"/>

<TextView android:id="@+id/away_goals" style="@style/goals"/>

</LinearLayout>

</LinearLayout>
6
public class TeamScore {

private final String name;

private final int goals;
//constructor and getters

}
public class MatchResult {

private final TeamScore homeTeam;

private final TeamScore awayTeam;

private final String gifUrl;
//constructor and getters

}
7
Butterknife Activity
@Bind(R.id.result_gif) ImageView resultGif;

@Bind(R.id.home_team) TextView homeTeam;

@Bind(R.id.away_team) TextView awayTeam;

@Bind(R.id.home_goals) TextView homeGoals;

@Bind(R.id.away_goals) TextView awayGoals;



@Override protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.match_result);

ButterKnife.bind(this);

updateDetail(getIntent().getParcelableExtra("RESULT"));

}

private void updateDetail(MatchResult result) {

Glide.with(this).load(result.getGifUrl())

.placeholder(R.drawable.loading).into(resultGif);

if (result.getHomeTeam() != null) {

homeTeam.setText(result.getHomeTeam().getName());

homeGoals.setText(Integer.toString(result.getHomeTeam().getGoals()));

}

if (result.getAwayTeam() != null) {

awayTeam.setText(result.getAwayTeam().getName());

awayGoals.setText(Integer.toString(result.getAwayTeam().getGoals()));

}

}
DroidCon Italy - Torino - April 2016 - @fabioCollini 8
1Data Binding basics
9
Google I/O 2015
10
Is Data Binding still beta?
11
Is Data Binding still beta?
dataBinding {

enabled = true

}

12
build.gradle
android {

compileSdkVersion 23

buildToolsVersion "23.0.2"



defaultConfig {

//...

____}

buildTypes {

//...

____}
}
<?xml version="1.0" encoding="utf-8"?>

<layout>

<LinearLayout style=“@style/root_layout"
xmlns:android="http://schemas.android.com/apk/res/android">



<ImageView android:id="@+id/result_gif" style="@style/gif"/>



<LinearLayout style="@style/team_layout">

<TextView android:id="@+id/home_team" style="@style/name"/>

<TextView android:id="@+id/home_goals" style="@style/goals"/>

</LinearLayout>



<LinearLayout style="@style/team_layout">

<TextView android:id="@+id/away_team" style="@style/name"/>

<TextView android:id="@+id/away_goals" style="@style/goals"/>

</LinearLayout>

</LinearLayout>

</layout>
13
Data Binding layout
<LinearLayout style="@style/root_layout"

xmlns:android=“http://schemas.android.com/apk/res/android">


<ImageView android:id="@+id/result_gif" style="@style/gif"/>



<LinearLayout style="@style/team_layout">

<TextView android:id="@+id/home_team" style="@style/name"/>

<TextView android:id="@+id/home_goals" style="@style/goals"/>

</LinearLayout>



<LinearLayout style="@style/team_layout">

<TextView android:id="@+id/away_team" style="@style/name"/>

<TextView android:id="@+id/away_goals" style="@style/goals"/>

</LinearLayout>

</LinearLayout>
<?xml version="1.0" encoding="utf-8"?>
<layout>
</layout>
<LinearLayout style="@style/root_layout"

xmlns:android=“http://schemas.android.com/apk/res/android">


<ImageView android:id="@+id/result_gif" style="@style/gif"/>



<LinearLayout style="@style/team_layout">

<TextView android:id="@+id/home_team" style="@style/name"/>

<TextView android:id="@+id/home_goals" style="@style/goals"/>

</LinearLayout>



<LinearLayout style="@style/team_layout">

<TextView android:id="@+id/away_team" style="@style/name"/>

<TextView android:id="@+id/away_goals" style="@style/goals"/>

</LinearLayout>

</LinearLayout>
14
One layout traversal
match_result.xmlMatchResultBinding.java
Auto generated class
<?xml version="1.0" encoding="utf-8"?>
<layout>
</layout>
public class MatchResultBinding extends
android.databinding.ViewDataBinding {



// ...

public final android.widget.ImageView resultGif;

public final android.widget.TextView homeTeam;

public final android.widget.TextView homeGoals;

public final android.widget.TextView awayTeam;

public final android.widget.TextView awayGoals;

// ...

}
15
Activity


@Override protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

binding = DataBindingUtil.setContentView(this, R.layout.match_result);
updateDetail(getIntent().getParcelableExtra("RESULT"));

}____


private void updateDetail(MatchResult result) {

Glide.with(this).load(result.getGifUrl())

.placeholder(R.drawable.loading).into(binding.resultGif);

if (result.getHomeTeam() != null) {

binding.homeTeam.setText(result.getHomeTeam().getName());

binding.homeGoals.setText(Integer.toString(result.getHomeTeam().getGoals()));

}___

if (result.getAwayTeam() != null) {

binding.awayTeam.setText(result.getAwayTeam().getName());

binding.awayGoals.setText(Integer.toString(result.getAwayTeam().getGoals()));

}__

}_
private MatchResultBinding binding;__
16
Variable in layout
<?xml version="1.0" encoding="utf-8"?>

<layout xmlns:android="http://schemas.android.com/apk/res/android">
Automatic null check
<data>

<variable name="result"
type="it.droidcon.databinding.MatchResult"/>

</data>
<LinearLayout style="@style/root_layout">

<ImageView android:id="@+id/result_gif" style="@style/gif"/>



<LinearLayout style="@style/team_layout">

<TextView style=“@style/name"

android:text="@{result.homeTeam.name}"/>

<TextView style="@style/goals"

android:text="@{Integer.toString(result.homeTeam.goals)}"/>

</LinearLayout>



<LinearLayout style="@style/team_layout">

<TextView style="@style/name"

android:text="@{result.awayTeam.name}"/>

<TextView style="@style/goals"

android:text="@{Integer.toString(result.awayTeam.goals)}"/>

</LinearLayout>

</LinearLayout>

</layout>
17
Activity
private MatchResultBinding binding;


@Override protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

binding = DataBindingUtil.setContentView(this, R.layout.match_result);
updateDetail(getIntent().getParcelableExtra("RESULT"));

}____


private void updateDetail(MatchResult result) {

Glide.with(this).load(result.getGifUrl())

.placeholder(R.drawable.loading).into(binding.resultGif);

binding.setResult(result);
}_
18
Code in XML?
Are you serious?!?
19
Complex code in XML is
NOT
a best practice
DroidCon Italy - Torino - April 2016 - @fabioCollini 20
2Custom attributes
21
@BindingAdapter
<ImageView android:id="@+id/result_gif" style="@style/gif"/>
private void updateDetail(MatchResult result) {

binding.setResult(result);

Glide.with(this).load(result.getGifUrl())

.placeholder(R.drawable.loading).into(binding.resultGif);

}
<ImageView style=“@style/gif" app:imageUrl="@{result.gifUrl}"/>
@BindingAdapter("imageUrl")

public static void loadImage(ImageView view, String url) {

Glide.with(view.getContext()).load(url)

.placeholder(R.drawable.loading).into(view);

}
22
public class MatchResultActivity extends AppCompatActivity {



@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

MatchResultBinding binding =

DataBindingUtil.setContentView(this, R.layout.match_result);

MatchResult result = getIntent().getParcelableExtra("RESULT");

binding.setResult(result);

}

}
23
Multiple parameters
@BindingAdapter({"imageUrl", "placeholder"})

public static void loadImage(ImageView view,
String url, Drawable placeholder) {

Glide.with(view.getContext()).load(url)

.placeholder(placeholder).into(view);

}

<ImageView
style="@style/gif"

app:imageUrl="@{result.gifUrl}"
app:placeholder="@{@drawable/loading}"/>
Annotated methods are static but…
@BindingAdapter("something")

public static void bindSomething(View view, AnyObject b) {

MyBinding binding = DataBindingUtil.findBinding(view);


MyObject myObject = binding.getMyObject();

//…
TextView myTextView = 

binding.myTextView;
//…
}
Can be any object
Get the layout binding
Get the connected objects
Access to all the views
Can be defined anywhere Can be used everywhere
Can be any View
25
BindingConversion
@BindingConversion

public static @ColorRes int convertEnumToColor(MyEnum value) {

switch (value) {

case VALUE1:

return R.color.color1;

case VALUE2:

return R.color.color2;

case VALUE3:

return R.color.color3;

default:

return R.color.color4;

}

}
<TextView

android:layout_width="wrap_content"

android:layout_height="wrap_content"

android:textColor="@{myObject.myEnum}"/>
@BindingConversion

public static String convertScoreToString(TeamScore score) {

return Integer.toString(score.getGoals());

}___

<TextView style="@style/goals”
android:text="@{result.awayTeam}"/>

26
BindingConversion & BindingAdapter
<TextView style="@style/goals"

android:text="@{Integer.toString(result.awayTeam.goals)}"/>
<TextView style="@style/goals"
app:goals="@{result.awayTeam.goals}"/>
@BindingAdapter("goals")

public static void bindGoals(TextView view, int goals) {

view.setText(Integer.toString(goals));

}__

@BindingConversion

public static String convertScoreToString(TeamScore score) {

return Integer.toString(score.getGoals());

}___

27
BindingConversion & BindingAdapter
<TextView style="@style/goals"

android:text="@{Integer.toString(result.awayTeam.goals)}"/>
<TextView style="@style/goals”
android:text="@{result.awayTeam}"/>

<TextView style="@style/goals"
app:goals="@{result.awayTeam.goals}"/>
@BindingAdapter("goals")

public static void bindGoals(TextView view, int goals) {

view.setText(Integer.toString(goals));

}__

@BindingConversion

public static String convertScoreToString(TeamScore score) {

return Integer.toString(score.getGoals());

}___

<TextView style="@style/goals”
android:text="@{result.awayTeam}"/>

28
BindingConversion & BindingAdapter
<TextView style="@style/goals"

android:text="@{Integer.toString(result.awayTeam.goals)}"/>
29
FontBinding
DroidCon Italy - Torino - April 2016 - @fabioCollini 30
3Components
31
<layout xmlns:android="http://schemas.android.com/apk/res/android"

xmlns:app="http://schemas.android.com/apk/res-auto">

<data>

<variable name="result"

type="it.droidcon.databinding.MatchResult"/>

</data>

<LinearLayout style="@style/root_layout">

<ImageView style="@style/gif" app:imageUrl="@{result.gifUrl}"/>





<LinearLayout style="@style/team_layout">

<TextView style="@style/name"

android:text="@{result.awayTeam.name}"/>

<TextView style="@style/goals"

app:goals="@{result.awayTeam.goals}"/>

</LinearLayout>

</LinearLayout>

</layout>
<LinearLayout style="@style/team_layout">

<TextView style="@style/name"

android:text="@{result.homeTeam.name}"/>

<TextView style="@style/goals"

app:goals="@{result.homeTeam.goals}"/>

</LinearLayout>
32
<layout
xmlns:android="http://schemas.android.com/apk/res/android"

xmlns:app="http://schemas.android.com/apk/res-auto">

</layout>
team_detail.xml
<data>

<variable name="team"

type="it.droidcon.databinding.TeamScore"/>

</data>

<LinearLayout style="@style/team_layout">

<TextView style="@style/name"

android:text="@{team.name}"/>

<TextView style="@style/goals"

app:goals="@{team.goals}"/>

</LinearLayout>
</data>

<LinearLayout style="@style/root_layout">

<ImageView style="@style/gif" app:imageUrl="@{result.gifUrl}"/>





<include layout="@layout/team_detail"/>
<include layout="@layout/team_detail"/>
</LinearLayout>

</layout>
<layout xmlns:android="http://schemas.android.com/apk/res/android"

xmlns:app="http://schemas.android.com/apk/res-auto">

<data>

<variable name="result"

type=“it.droidcon.databinding.MatchResult"/>


</data>

<LinearLayout style="@style/root_layout">

<ImageView style="@style/gif" app:imageUrl="@{result.gifUrl}"/>





<layout xmlns:android="http://schemas.android.com/apk/res/android"

xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:bind="http://schemas.android.com/tools">

<data>

<variable name="result"

type="it.droidcon.databinding.MatchResult"/>

<include layout="@layout/team_detail"

/>
<include layout="@layout/team_detail"

/>
</LinearLayout>

</layout>
bind:team="@{result.homeTeam}"
bind:team="@{result.awayTeam}"
</data>

<LinearLayout style="@style/root_layout"
>

<ImageView style="@style/gif" app:imageUrl="@{result.gifUrl}"/>





android:background="@{backgroundColor ?? @color/color1}"
<layout xmlns:android="http://schemas.android.com/apk/res/android"

xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:bind="http://schemas.android.com/tools">

<data>

<variable name="result"

type="it.droidcon.databinding.MatchResult"/>

<include layout="@layout/team_detail"

/>
<include layout="@layout/team_detail"

/>
</LinearLayout>

</layout>
bind:team="@{result.homeTeam}"
bind:team="@{result.awayTeam}"
<variable name="backgroundColor" type="Integer" />
DroidCon Italy - Torino - April 2016 - @fabioCollini 36
4Two Way Data Binding
37
38
public class ContactInfo {

public String message;



public boolean messageAvailable;

}__
39
public class ContactInfo {

public String message;



public boolean messageAvailable;

}__
<layout xmlns:android="http://schemas.android.com/apk/res/android">

<data>

<variable name="info"

type="it.droidcon.databinding.ContactInfo" />

</data>



<LinearLayout style="@style/contact_root">

<EditText

style="@style/contact_text"

android:enabled="@{info.messageAvailable}"

android:text="@{info.message}" />



<Button

style="@style/contact_button"

android:enabled="@{info.messageAvailable}"

android:onClick="send" />

</LinearLayout>

</layout>
40
public class ContactInfo {

public String message;



public boolean messageAvailable;

}__
public class ContactActivity extends AppCompatActivity {

private ContactInfo contactInfo;

private ContactBinding binding;



@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

binding = DataBindingUtil.setContentView(this,
R.layout.contact);

contactInfo = new ContactInfo();

binding.setInfo(contactInfo);



binding.getRoot().postDelayed(() -> {

contactInfo.message = "my message";

contactInfo.messageAvailable = true;

}, 2000);

}



public void send(View view) {

Snackbar.make(binding.getRoot(),
contactInfo.message, LENGTH_LONG).show();

}

}
41
42
Views are not automatically updated :(
package android.databinding;



public interface Observable {



void addOnPropertyChangedCallback(
OnPropertyChangedCallback callback);



void removeOnPropertyChangedCallback(
OnPropertyChangedCallback callback);



abstract class OnPropertyChangedCallback {

public abstract void onPropertyChanged(
Observable sender, int propertyId);

}

}
43
Observable hierarchy
public String getMessage() {

return message;

}____



public boolean isMessageAvailable() {

return messageAvailable;

}___



public void setMessage(String message) {

this.message = message;



}__



public void setMessageAvailable(boolean messageAvailable) {

this.messageAvailable = messageAvailable;



}_

public class ContactInfo

private String message;



private boolean messageAvailable;

44
extends BaseObservable {
}
notifyPropertyChanged(BR.message);
notifyPropertyChanged(BR.messageAvailable);
@Bindable
@Bindable
45
public class ContactInfo {

public final ObservableField<String> message = new ObservableField<>();_



public final ObservableBoolean messageAvailable = new ObservableBoolean();_

}__
46
public class ContactInfo {

public final ObservableField<String> message = new ObservableField<>();_



public final ObservableBoolean messageAvailable = new ObservableBoolean();_

}__
public class ContactActivity extends AppCompatActivity {

private ContactInfo contactInfo;

private ContactBinding binding;



@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

binding = DataBindingUtil.setContentView(this,
R.layout.contact);

contactInfo = new ContactInfo();

binding.setInfo(contactInfo);



binding.getRoot().postDelayed(() -> {

contactInfo.message.set("my message");

contactInfo.messageAvailable.set(true);

}, 2000);
}___



public void send(View view) {

Snackbar.make(binding.getRoot(),
contactInfo.message.get(), LENGTH_LONG).show();

}__

}_
<layout xmlns:android="http://schemas.android.com/apk/res/android">

<data>

<variable name="info"

type="it.droidcon.databinding.ContactInfo" />

</data>



<LinearLayout style="@style/contact_root">

<EditText

style="@style/contact_text"

android:enabled="@{info.messageAvailable}"

android:text="@{info.message}" />



<Button

style="@style/contact_button"

android:enabled="@{info.messageAvailable}"

android:onClick="send" />

</LinearLayout>

</layout>
47
public class ContactInfo {

public final ObservableField<String> message = new ObservableField<>();_



public final ObservableBoolean messageAvailable = new ObservableBoolean();_

}__
ObservableField<String>
ObservableBoolean
ObservableBoolean
48
49
Two way Data Binding
@BindingAdapter("binding")

public static void bindEditText(EditText view,
final ObservableString observable) {

Pair<ObservableString, TextWatcherAdapter> pair =
(Pair) view.getTag(R.id.bound_observable);

if (pair == null || pair.first != observable) {

if (pair != null)

view.removeTextChangedListener(pair.second);

TextWatcherAdapter watcher = new TextWatcherAdapter() {

@Override
public void onTextChanged(CharSequence s, int a, int b, int c) {

observable.set(s.toString());

}

};

view.setTag(R.id.bound_observable, new Pair<>(observable, watcher));

view.addTextChangedListener(watcher);

}

String newValue = observable.get();

if (!view.getText().toString().equals(newValue))

view.setText(newValue);

}

medium.com/@fabioCollini/android-data-binding-f9f9d3afc761
50
51
<layout xmlns:android="http://schemas.android.com/apk/res/android">

<data>

<variable name="info"

type="it.droidcon.databinding.ContactInfo" />

</data>



<LinearLayout style="@style/contact_root">

<EditText

style="@style/contact_text"

android:enabled="@{info.messageAvailable}"

android:text="@={info.message}" />



<Button

style="@style/contact_button"

android:enabled="@{info.messageAvailable}"

android:onClick="send" />

</LinearLayout>

</layout>
Two way data binding
52
53
54
Layout
ContactInfo
Binding
TextWatcherset(…)
addOnProperty
ChangedCallbackset(…)
if (changed)
WeakReference
if (changed)
DroidCon Italy - Torino - April 2016 - @fabioCollini 55
5MVVM
56
MatchResultViewModel
public class MatchResultViewModel {


public final ObservableField<MatchResult> result =
new ObservableField<>();



public final ObservableBoolean loading =
new ObservableBoolean();



public void reload() {
loading.set(true);

reloadInBackground(result -> {

loading.set(false);

this.result.set(result);

});

}

}
<layout xmlns:android="http://schemas.android.com/apk/res/android"

xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:bind="http://schemas.android.com/tools">

<data>

<variable name="viewModel"

type="it.droidcon.databinding.MatchResultViewModel"/>

</data>

<LinearLayout style="@style/root_layout">

<ImageView style="@style/gif"
app:imageUrl="@{viewModel.result.gifUrl}"/>





<include layout="@layout/team_detail"

/>
<include layout="@layout/team_detail"

/>
</LinearLayout>

</layout>
bind:team="@{viewModel.result.homeTeam}"
bind:team="@{viewModel.result.awayTeam}"
ObservableField
58
Visibility
<FrameLayout style="@style/progress_layout"

android:visibility=
"@{viewModel.loading ? View.VISIBLE : View.GONE}">

<ProgressBar style="@style/progress"/>

</FrameLayout>
<?xml version="1.0" encoding="utf-8"?>

<layout xmlns:android="http://schemas.android.com/apk/res/android"

xmlns:app="http://schemas.android.com/apk/res-auto"

xmlns:bind="http://schemas.android.com/tools">

<data>
<import type="android.view.View"/>

<variable name="viewModel"

type="it.droidcon.databinding.MatchResultViewModel"/>
</data>

<FrameLayout style="@style/main_container">


<LinearLayout style="@style/root_layout">

<!-- ... -->

</LinearLayout>





</FrameLayout>

</layout>
59
Visibility
<FrameLayout style="@style/progress_layout"

android:visibility=
"@{viewModel.loading ? View.VISIBLE : View.GONE}">

<ProgressBar style="@style/progress"/>

</FrameLayout>
@BindingConversion

public static int convertBooleanToVisibility(boolean b) {

return b ? View.VISIBLE : View.GONE;

}___

60
Visibility
<FrameLayout style="@style/progress_layout"

android:visibility="@{viewModel.loading}">

<ProgressBar style="@style/progress"/>

</FrameLayout>
@BindingConversion

public static int convertBooleanToVisibility(boolean b) {

return b ? View.VISIBLE : View.GONE;

}___

@BindingAdapter("visibleOrGone")

public static void bindVisibleOrGone(View view, boolean b) {

view.setVisibility(b ? View.VISIBLE : View.GONE);

}____
61
Visibility
<FrameLayout style="@style/progress_layout"

app:visibleOrGone="@{viewModel.loading}">

<ProgressBar style="@style/progress"/>

</FrameLayout>
@BindingConversion

public static int convertBooleanToVisibility(boolean b) {

return b ? View.VISIBLE : View.GONE;

}___

@BindingAdapter("visibleOrGone")

public static void bindVisibleOrGone(View view, boolean b) {

view.setVisibility(b ? View.VISIBLE : View.GONE);

}____
@BindingAdapter("visible")

public static void bindVisible(View view, boolean b) {

view.setVisibility(b ? View.VISIBLE : View.INVISIBLE);

}
<LinearLayout style="@style/root_layout"

android:onClick="@{???}">

<!-- ... -->

</LinearLayout>

62
}___
public class MatchResultViewModel {
public final ObservableField<MatchResult> result =
new ObservableField<>();

public final ObservableBoolean loading = new ObservableBoolean();

public void reload() {
loading.set(true);

reloadInBackground(result -> {

loading.set(false);

this.result.set(result);

});

}__
public final_View.OnClickListener reloadClickListener =
new View.OnClickListener() {

@Override public void onClick(View v) {

reload();

}_

};

<LinearLayout style="@style/root_layout"

android:onClick="@{viewModel.reloadClickListener}">

<!-- ... -->

</LinearLayout>

63
}___
public class MatchResultViewModel {
public final ObservableField<MatchResult> result =
new ObservableField<>();

public final ObservableBoolean loading = new ObservableBoolean();

public void reload() {
loading.set(true);

reloadInBackground(result -> {

loading.set(false);

this.result.set(result);

});

}__
<LinearLayout style="@style/root_layout"

android:onClick="@{viewModel::reload}">

<!-- ... -->

</LinearLayout>

64
}___
public class MatchResultViewModel {
public final ObservableField<MatchResult> result =
new ObservableField<>();

public final ObservableBoolean loading = new ObservableBoolean();

public void reload(View v) {
loading.set(true);

reloadInBackground(result -> {

loading.set(false);

this.result.set(result);

});

}__
<LinearLayout style="@style/root_layout"

android:onClick="@{v -> viewModel.reload()}">

<!-- ... -->

</LinearLayout>

65
}___
public class MatchResultViewModel {
public final ObservableField<MatchResult> result =
new ObservableField<>();

public final ObservableBoolean loading = new ObservableBoolean();

public void reload() {
loading.set(true);

reloadInBackground(result -> {

loading.set(false);

this.result.set(result);

});

}__
public class MatchResultViewModel {
public final ObservableField<MatchResult> result =
new ObservableField<>();

public final ObservableBoolean loading = new ObservableBoolean();

public void reload() {
loading.set(true);

reloadInBackground(result -> {

loading.set(false);

this.result.set(result);

});

}__
66
}___
@BindingAdapter("android:onClick")

public static void bindOnClick(View view, final Runnable listener) {

view.setOnClickListener(new View.OnClickListener() {

@Override public void onClick(View v) {

listener.run();

}____

});

}___
<LinearLayout style="@style/root_layout"

android:onClick="@{v -> viewModel.reload()}">

<!-- ... -->

</LinearLayout>

public class MatchResultViewModel {
public final ObservableField<MatchResult> result =
new ObservableField<>();

public final ObservableBoolean loading = new ObservableBoolean();

public void reload() {
loading.set(true);

reloadInBackground(result -> {

loading.set(false);

this.result.set(result);

});

}__
<LinearLayout style="@style/root_layout"

android:onClick="@{viewModel::reload}">

<!-- ... -->

</LinearLayout>

67
}___
@BindingAdapter("android:onClick")

public static void bindOnClick(View view, final Runnable listener) {

view.setOnClickListener(new View.OnClickListener() {

@Override public void onClick(View v) {

listener.run();

}____

});

}___
68
Final layout
<?xml version="1.0" encoding="utf-8"?>

<layout xmlns:android="http://schemas.android.com/apk/res/android"

xmlns:app="http://schemas.android.com/apk/res-auto"

xmlns:bind="http://schemas.android.com/tools">

<data>

<!-- ... -->

</data>

<FrameLayout style="@style/main_container">


<LinearLayout style="@style/root_layout"

android:onClick=“@{viewModel::reload}”>

<!-- ... -->

</LinearLayout>



<FrameLayout style="@style/progress_layout"

app:visibleOrGone="@{viewModel.loading}">

<ProgressBar style="@style/progress"/>

</FrameLayout>



</FrameLayout>

</layout>
69
public interface Reloadable {

String getErrorMessage();



void reload();

}

<layout xmlns:android="http://schemas.android.com/apk/res/android">

<data>

<variable name="reloadable"

type="it.droidcon.databinding.Reloadable"/>

</data>



<LinearLayout style="@style/reload_layout">

<TextView

style="@style/error_message"

android:text="@{reloadable.errorMessage}"/>



<Button

style="@style/reload"

android:onClick="@{reloadable::reload}"

android:text="@string/reload"/>

</LinearLayout>

</layout>
70
Model View ViewModel
View
ViewModel
Model
DataBinding
Retained on
configuration change
Saved in Activity or
Fragment state
Activity or Fragment
71
github.com/fabioCollini/mv2m
Android MVVM lightweight library based on
Android Data Binding
View ViewModel RetrofitService
reload
update
binding
Model
View ViewModel RetrofitServiceModel
request
response
binding
Testable code
Data binding and MVVM
MockService
MockService
RetrofitService
RetrofitServiceViewModel
reload
update
Model
request
response
JVM Test
ViewModel ModelJVM Test
assert
when().thenReturn()
verify
MockServiceRetrofitService
MockServiceRetrofitService
View ViewModel
perform(click())
update
binding
Model
request
response
EspressoTest
View ViewModel ModelEspressoTest
onView
verify
when().thenReturn()
reload
binding
76
Data binding
You can write all your business logic
in an huge xml file
————————————————————————
————————————
Custom attributes Reusable UI code
77
Data binding
You can write all your business logic
in an huge xml file
————————————————————————
————————————
Includes UI components
MVVM Testable code
78
Thanks for your attention!
androidavanzato.it
Questions?
79
Links
developer.android.com/tools/data-binding/guide.html
Is Databinding still beta? - Google plus
medium.com/@fabioCollini/android-data-binding-f9f9d3afc761
github.com/fabioCollini/mv2m
github.com/commit-non-javisti/CoseNonJavisteAndroidApp
halfthought.wordpress.com/2016/03/23/2-way-data-binding-on-android

Mais conteúdo relacionado

Mais procurados

Data binding 入門淺談
Data binding 入門淺談Data binding 入門淺談
Data binding 入門淺談awonwon
 
Vaadin Components @ Angular U
Vaadin Components @ Angular UVaadin Components @ Angular U
Vaadin Components @ Angular UJoonas Lehtinen
 
Vaadin DevDay 2017 - DI your UI
Vaadin DevDay 2017 - DI your UIVaadin DevDay 2017 - DI your UI
Vaadin DevDay 2017 - DI your UIPeter Lehto
 
Vaadin DevDay 2017 - Data Binding in Vaadin 8
Vaadin DevDay 2017 - Data Binding in Vaadin 8Vaadin DevDay 2017 - Data Binding in Vaadin 8
Vaadin DevDay 2017 - Data Binding in Vaadin 8Peter Lehto
 
Vaadin 8 with Spring Framework
Vaadin 8 with Spring FrameworkVaadin 8 with Spring Framework
Vaadin 8 with Spring FrameworkPeter Lehto
 
Vaadin 8 with Spring Frameworks AutoConfiguration
Vaadin 8 with Spring Frameworks AutoConfigurationVaadin 8 with Spring Frameworks AutoConfiguration
Vaadin 8 with Spring Frameworks AutoConfigurationPeter Lehto
 
Building impressive layout systems with vaadin
Building impressive layout systems with vaadinBuilding impressive layout systems with vaadin
Building impressive layout systems with vaadinPeter Lehto
 
Building web apps with Vaadin 8
Building web apps with Vaadin 8 Building web apps with Vaadin 8
Building web apps with Vaadin 8 Marcus Hellberg
 
Vaadin Flow - JavaLand 2018
Vaadin Flow - JavaLand 2018Vaadin Flow - JavaLand 2018
Vaadin Flow - JavaLand 2018Peter Lehto
 
Techlunch - Dependency Injection with Vaadin
Techlunch - Dependency Injection with VaadinTechlunch - Dependency Injection with Vaadin
Techlunch - Dependency Injection with VaadinPeter Lehto
 
What's new in Vaadin 8, how do you upgrade, and what's next?
What's new in Vaadin 8, how do you upgrade, and what's next?What's new in Vaadin 8, how do you upgrade, and what's next?
What's new in Vaadin 8, how do you upgrade, and what's next?Marcus Hellberg
 
GWT integration with Vaadin
GWT integration with VaadinGWT integration with Vaadin
GWT integration with VaadinPeter Lehto
 
Infinum Android Talks #14 - Data binding to the rescue... or not (?) by Krist...
Infinum Android Talks #14 - Data binding to the rescue... or not (?) by Krist...Infinum Android Talks #14 - Data binding to the rescue... or not (?) by Krist...
Infinum Android Talks #14 - Data binding to the rescue... or not (?) by Krist...Infinum
 
Vaadin DevDay 2017 - Web Components
Vaadin DevDay 2017 - Web ComponentsVaadin DevDay 2017 - Web Components
Vaadin DevDay 2017 - Web ComponentsPeter Lehto
 
當ZK遇見Front-End
當ZK遇見Front-End當ZK遇見Front-End
當ZK遇見Front-End祁源 朱
 
Creating lightweight JS Apps w/ Web Components and lit-html
Creating lightweight JS Apps w/ Web Components and lit-htmlCreating lightweight JS Apps w/ Web Components and lit-html
Creating lightweight JS Apps w/ Web Components and lit-htmlIlia Idakiev
 
Binding business data to vaadin components
Binding business data to vaadin componentsBinding business data to vaadin components
Binding business data to vaadin componentsPeter Lehto
 

Mais procurados (20)

Data binding 入門淺談
Data binding 入門淺談Data binding 入門淺談
Data binding 入門淺談
 
Vaadin Components @ Angular U
Vaadin Components @ Angular UVaadin Components @ Angular U
Vaadin Components @ Angular U
 
Vaadin DevDay 2017 - DI your UI
Vaadin DevDay 2017 - DI your UIVaadin DevDay 2017 - DI your UI
Vaadin DevDay 2017 - DI your UI
 
Vaadin Components
Vaadin ComponentsVaadin Components
Vaadin Components
 
Vaadin DevDay 2017 - Data Binding in Vaadin 8
Vaadin DevDay 2017 - Data Binding in Vaadin 8Vaadin DevDay 2017 - Data Binding in Vaadin 8
Vaadin DevDay 2017 - Data Binding in Vaadin 8
 
Vaadin 8 with Spring Framework
Vaadin 8 with Spring FrameworkVaadin 8 with Spring Framework
Vaadin 8 with Spring Framework
 
Vaadin 8 with Spring Frameworks AutoConfiguration
Vaadin 8 with Spring Frameworks AutoConfigurationVaadin 8 with Spring Frameworks AutoConfiguration
Vaadin 8 with Spring Frameworks AutoConfiguration
 
Building impressive layout systems with vaadin
Building impressive layout systems with vaadinBuilding impressive layout systems with vaadin
Building impressive layout systems with vaadin
 
Building web apps with Vaadin 8
Building web apps with Vaadin 8 Building web apps with Vaadin 8
Building web apps with Vaadin 8
 
Vaadin Flow - JavaLand 2018
Vaadin Flow - JavaLand 2018Vaadin Flow - JavaLand 2018
Vaadin Flow - JavaLand 2018
 
Techlunch - Dependency Injection with Vaadin
Techlunch - Dependency Injection with VaadinTechlunch - Dependency Injection with Vaadin
Techlunch - Dependency Injection with Vaadin
 
What's new in Vaadin 8, how do you upgrade, and what's next?
What's new in Vaadin 8, how do you upgrade, and what's next?What's new in Vaadin 8, how do you upgrade, and what's next?
What's new in Vaadin 8, how do you upgrade, and what's next?
 
GWT integration with Vaadin
GWT integration with VaadinGWT integration with Vaadin
GWT integration with Vaadin
 
Infinum Android Talks #14 - Data binding to the rescue... or not (?) by Krist...
Infinum Android Talks #14 - Data binding to the rescue... or not (?) by Krist...Infinum Android Talks #14 - Data binding to the rescue... or not (?) by Krist...
Infinum Android Talks #14 - Data binding to the rescue... or not (?) by Krist...
 
Vaadin 8 and 10
Vaadin 8 and 10Vaadin 8 and 10
Vaadin 8 and 10
 
Vaadin DevDay 2017 - Web Components
Vaadin DevDay 2017 - Web ComponentsVaadin DevDay 2017 - Web Components
Vaadin DevDay 2017 - Web Components
 
當ZK遇見Front-End
當ZK遇見Front-End當ZK遇見Front-End
當ZK遇見Front-End
 
Knockoutjs
KnockoutjsKnockoutjs
Knockoutjs
 
Creating lightweight JS Apps w/ Web Components and lit-html
Creating lightweight JS Apps w/ Web Components and lit-htmlCreating lightweight JS Apps w/ Web Components and lit-html
Creating lightweight JS Apps w/ Web Components and lit-html
 
Binding business data to vaadin components
Binding business data to vaadin componentsBinding business data to vaadin components
Binding business data to vaadin components
 

Destaque

Introduction to Retrofit and RxJava
Introduction to Retrofit and RxJavaIntroduction to Retrofit and RxJava
Introduction to Retrofit and RxJavaFabio Collini
 
Evolving the Android Core with Aspects
Evolving the Android Core with AspectsEvolving the Android Core with Aspects
Evolving the Android Core with AspectsCarlo Pescio
 
Internal Android Library Management (DroidCon SF 2016, Droidcon Italy 2016)
Internal Android Library Management (DroidCon SF 2016, Droidcon Italy 2016)Internal Android Library Management (DroidCon SF 2016, Droidcon Italy 2016)
Internal Android Library Management (DroidCon SF 2016, Droidcon Italy 2016)Kelly Shuster
 
Android Wear CodeLab - GDG Firenze
Android Wear CodeLab - GDG FirenzeAndroid Wear CodeLab - GDG Firenze
Android Wear CodeLab - GDG FirenzeFabio Collini
 
Testable Android Apps DroidCon Italy 2015
Testable Android Apps DroidCon Italy 2015Testable Android Apps DroidCon Italy 2015
Testable Android Apps DroidCon Italy 2015Fabio Collini
 
Testable Android Apps using data binding and MVVM
Testable Android Apps using data binding and MVVMTestable Android Apps using data binding and MVVM
Testable Android Apps using data binding and MVVMFabio Collini
 
World-Class Testing Development Pipeline for Android
 World-Class Testing Development Pipeline for Android World-Class Testing Development Pipeline for Android
World-Class Testing Development Pipeline for AndroidPedro Vicente Gómez Sánchez
 
Mastering the NDK with Android Studio 2.0 and the gradle-experimental plugin
Mastering the NDK with Android Studio 2.0 and the gradle-experimental pluginMastering the NDK with Android Studio 2.0 and the gradle-experimental plugin
Mastering the NDK with Android Studio 2.0 and the gradle-experimental pluginXavier Hallade
 
Beyond Android Views - Window,Surface,Special Views,and More
Beyond Android Views - Window,Surface,Special Views,and MoreBeyond Android Views - Window,Surface,Special Views,and More
Beyond Android Views - Window,Surface,Special Views,and Morerogeryi
 
Android Custom Views
Android Custom ViewsAndroid Custom Views
Android Custom ViewsBabar Sanah
 
Android Development - ConstraintLayout
Android Development - ConstraintLayoutAndroid Development - ConstraintLayout
Android Development - ConstraintLayoutManuel Vicente Vivo
 
Clean android code - Droidcon Italiy 2014
Clean android code - Droidcon Italiy 2014Clean android code - Droidcon Italiy 2014
Clean android code - Droidcon Italiy 2014Fabio Collini
 
Android Widget @ whymca 2011
Android Widget @ whymca 2011Android Widget @ whymca 2011
Android Widget @ whymca 2011Fabio Collini
 
Librerie su Android: come non reinventare la ruota @ whymca 2012
Librerie su Android: come non reinventare la ruota @ whymca 2012 Librerie su Android: come non reinventare la ruota @ whymca 2012
Librerie su Android: come non reinventare la ruota @ whymca 2012 Fabio Collini
 
Model-View-ViewModel and RxJava
Model-View-ViewModel and RxJavaModel-View-ViewModel and RxJava
Model-View-ViewModel and RxJavaFlorina Muntenescu
 
Journey of an event, the android touch - Marco Cova, Facebook
Journey of an event, the android touch - Marco Cova, FacebookJourney of an event, the android touch - Marco Cova, Facebook
Journey of an event, the android touch - Marco Cova, FacebookDroidConTLV
 
Acrhitecture deisign pattern_MVC_MVP_MVVM
Acrhitecture deisign pattern_MVC_MVP_MVVMAcrhitecture deisign pattern_MVC_MVP_MVVM
Acrhitecture deisign pattern_MVC_MVP_MVVMDong-Ho Lee
 

Destaque (20)

Introduction to Retrofit and RxJava
Introduction to Retrofit and RxJavaIntroduction to Retrofit and RxJava
Introduction to Retrofit and RxJava
 
Evolving the Android Core with Aspects
Evolving the Android Core with AspectsEvolving the Android Core with Aspects
Evolving the Android Core with Aspects
 
Internal Android Library Management (DroidCon SF 2016, Droidcon Italy 2016)
Internal Android Library Management (DroidCon SF 2016, Droidcon Italy 2016)Internal Android Library Management (DroidCon SF 2016, Droidcon Italy 2016)
Internal Android Library Management (DroidCon SF 2016, Droidcon Italy 2016)
 
Android Wear CodeLab - GDG Firenze
Android Wear CodeLab - GDG FirenzeAndroid Wear CodeLab - GDG Firenze
Android Wear CodeLab - GDG Firenze
 
Testable Android Apps DroidCon Italy 2015
Testable Android Apps DroidCon Italy 2015Testable Android Apps DroidCon Italy 2015
Testable Android Apps DroidCon Italy 2015
 
Android MVVM
Android MVVMAndroid MVVM
Android MVVM
 
Testable Android Apps using data binding and MVVM
Testable Android Apps using data binding and MVVMTestable Android Apps using data binding and MVVM
Testable Android Apps using data binding and MVVM
 
World-Class Testing Development Pipeline for Android
 World-Class Testing Development Pipeline for Android World-Class Testing Development Pipeline for Android
World-Class Testing Development Pipeline for Android
 
Building maintainable app
Building maintainable appBuilding maintainable app
Building maintainable app
 
Mastering the NDK with Android Studio 2.0 and the gradle-experimental plugin
Mastering the NDK with Android Studio 2.0 and the gradle-experimental pluginMastering the NDK with Android Studio 2.0 and the gradle-experimental plugin
Mastering the NDK with Android Studio 2.0 and the gradle-experimental plugin
 
Beyond Android Views - Window,Surface,Special Views,and More
Beyond Android Views - Window,Surface,Special Views,and MoreBeyond Android Views - Window,Surface,Special Views,and More
Beyond Android Views - Window,Surface,Special Views,and More
 
Android Custom Views
Android Custom ViewsAndroid Custom Views
Android Custom Views
 
Android Development - ConstraintLayout
Android Development - ConstraintLayoutAndroid Development - ConstraintLayout
Android Development - ConstraintLayout
 
Clean android code - Droidcon Italiy 2014
Clean android code - Droidcon Italiy 2014Clean android code - Droidcon Italiy 2014
Clean android code - Droidcon Italiy 2014
 
Android Widget @ whymca 2011
Android Widget @ whymca 2011Android Widget @ whymca 2011
Android Widget @ whymca 2011
 
Librerie su Android: come non reinventare la ruota @ whymca 2012
Librerie su Android: come non reinventare la ruota @ whymca 2012 Librerie su Android: come non reinventare la ruota @ whymca 2012
Librerie su Android: come non reinventare la ruota @ whymca 2012
 
Model-View-ViewModel and RxJava
Model-View-ViewModel and RxJavaModel-View-ViewModel and RxJava
Model-View-ViewModel and RxJava
 
Journey of an event, the android touch - Marco Cova, Facebook
Journey of an event, the android touch - Marco Cova, FacebookJourney of an event, the android touch - Marco Cova, Facebook
Journey of an event, the android touch - Marco Cova, Facebook
 
Introduction to Android Window System
Introduction to Android Window SystemIntroduction to Android Window System
Introduction to Android Window System
 
Acrhitecture deisign pattern_MVC_MVP_MVVM
Acrhitecture deisign pattern_MVC_MVP_MVVMAcrhitecture deisign pattern_MVC_MVP_MVVM
Acrhitecture deisign pattern_MVC_MVP_MVVM
 

Semelhante a Data Binding in Action using MVVM pattern

Effective Android Data Binding
Effective Android Data BindingEffective Android Data Binding
Effective Android Data BindingEric Maxwell
 
Android por onde começar? Mini Curso Erbase 2015
Android por onde começar? Mini Curso Erbase 2015 Android por onde começar? Mini Curso Erbase 2015
Android por onde começar? Mini Curso Erbase 2015 Mario Jorge Pereira
 
Crossing platforms with JavaScript & React
Crossing platforms with JavaScript & React Crossing platforms with JavaScript & React
Crossing platforms with JavaScript & React Robert DeLuca
 
TechDay: Kick Start Your Experience with Android Wear - Mario Viviani
TechDay: Kick Start Your Experience with Android Wear - Mario VivianiTechDay: Kick Start Your Experience with Android Wear - Mario Viviani
TechDay: Kick Start Your Experience with Android Wear - Mario VivianiCodemotion
 
Kick start your experience with android wear - Codemotion Rome 2015
Kick start your experience with android wear - Codemotion Rome 2015Kick start your experience with android wear - Codemotion Rome 2015
Kick start your experience with android wear - Codemotion Rome 2015Codemotion
 
[2019] 벅스 5.0 (feat. Kotlin, Jetpack)
[2019] 벅스 5.0 (feat. Kotlin, Jetpack)[2019] 벅스 5.0 (feat. Kotlin, Jetpack)
[2019] 벅스 5.0 (feat. Kotlin, Jetpack)NHN FORWARD
 
After max+phonegap
After max+phonegapAfter max+phonegap
After max+phonegapyangdj
 
混搭移动开发:PhoneGap+JQurey+Dreamweaver
混搭移动开发:PhoneGap+JQurey+Dreamweaver混搭移动开发:PhoneGap+JQurey+Dreamweaver
混搭移动开发:PhoneGap+JQurey+Dreamweaveryangdj
 
Progressive Enhancment with Rails and React
Progressive Enhancment with Rails and ReactProgressive Enhancment with Rails and React
Progressive Enhancment with Rails and ReactTyler Johnston
 
! Modernizr v2.0.6 httpwww.modernizr.com Copyri.docx
!  Modernizr v2.0.6  httpwww.modernizr.com   Copyri.docx!  Modernizr v2.0.6  httpwww.modernizr.com   Copyri.docx
! Modernizr v2.0.6 httpwww.modernizr.com Copyri.docxMARRY7
 
Data Binding - Android by Harin Trivedi
Data Binding - Android by Harin TrivediData Binding - Android by Harin Trivedi
Data Binding - Android by Harin Trivediharintrivedi
 
Slightly Advanced Android Wear ;)
Slightly Advanced Android Wear ;)Slightly Advanced Android Wear ;)
Slightly Advanced Android Wear ;)Alfredo Morresi
 
Backbone.js — Introduction to client-side JavaScript MVC
Backbone.js — Introduction to client-side JavaScript MVCBackbone.js — Introduction to client-side JavaScript MVC
Backbone.js — Introduction to client-side JavaScript MVCpootsbook
 
Big Data for each one of us
Big Data for each one of usBig Data for each one of us
Big Data for each one of usOSCON Byrum
 
SE2016 Android Mikle Anokhin "Speed up application development with data bind...
SE2016 Android Mikle Anokhin "Speed up application development with data bind...SE2016 Android Mikle Anokhin "Speed up application development with data bind...
SE2016 Android Mikle Anokhin "Speed up application development with data bind...Inhacking
 

Semelhante a Data Binding in Action using MVVM pattern (20)

Effective Android Data Binding
Effective Android Data BindingEffective Android Data Binding
Effective Android Data Binding
 
Android por onde começar? Mini Curso Erbase 2015
Android por onde começar? Mini Curso Erbase 2015 Android por onde começar? Mini Curso Erbase 2015
Android por onde começar? Mini Curso Erbase 2015
 
Crossing platforms with JavaScript & React
Crossing platforms with JavaScript & React Crossing platforms with JavaScript & React
Crossing platforms with JavaScript & React
 
TechDay: Kick Start Your Experience with Android Wear - Mario Viviani
TechDay: Kick Start Your Experience with Android Wear - Mario VivianiTechDay: Kick Start Your Experience with Android Wear - Mario Viviani
TechDay: Kick Start Your Experience with Android Wear - Mario Viviani
 
Kick start your experience with android wear - Codemotion Rome 2015
Kick start your experience with android wear - Codemotion Rome 2015Kick start your experience with android wear - Codemotion Rome 2015
Kick start your experience with android wear - Codemotion Rome 2015
 
[2019] 벅스 5.0 (feat. Kotlin, Jetpack)
[2019] 벅스 5.0 (feat. Kotlin, Jetpack)[2019] 벅스 5.0 (feat. Kotlin, Jetpack)
[2019] 벅스 5.0 (feat. Kotlin, Jetpack)
 
Backbone Basics with Examples
Backbone Basics with ExamplesBackbone Basics with Examples
Backbone Basics with Examples
 
Vaadin7
Vaadin7Vaadin7
Vaadin7
 
After max+phonegap
After max+phonegapAfter max+phonegap
After max+phonegap
 
混搭移动开发:PhoneGap+JQurey+Dreamweaver
混搭移动开发:PhoneGap+JQurey+Dreamweaver混搭移动开发:PhoneGap+JQurey+Dreamweaver
混搭移动开发:PhoneGap+JQurey+Dreamweaver
 
Progressive Enhancment with Rails and React
Progressive Enhancment with Rails and ReactProgressive Enhancment with Rails and React
Progressive Enhancment with Rails and React
 
70562 (1)
70562 (1)70562 (1)
70562 (1)
 
! Modernizr v2.0.6 httpwww.modernizr.com Copyri.docx
!  Modernizr v2.0.6  httpwww.modernizr.com   Copyri.docx!  Modernizr v2.0.6  httpwww.modernizr.com   Copyri.docx
! Modernizr v2.0.6 httpwww.modernizr.com Copyri.docx
 
Data Binding - Android by Harin Trivedi
Data Binding - Android by Harin TrivediData Binding - Android by Harin Trivedi
Data Binding - Android by Harin Trivedi
 
Clean Javascript
Clean JavascriptClean Javascript
Clean Javascript
 
Slightly Advanced Android Wear ;)
Slightly Advanced Android Wear ;)Slightly Advanced Android Wear ;)
Slightly Advanced Android Wear ;)
 
Backbone.js — Introduction to client-side JavaScript MVC
Backbone.js — Introduction to client-side JavaScript MVCBackbone.js — Introduction to client-side JavaScript MVC
Backbone.js — Introduction to client-side JavaScript MVC
 
Big Data for each one of us
Big Data for each one of usBig Data for each one of us
Big Data for each one of us
 
Introduction to AngularJS
Introduction to AngularJSIntroduction to AngularJS
Introduction to AngularJS
 
SE2016 Android Mikle Anokhin "Speed up application development with data bind...
SE2016 Android Mikle Anokhin "Speed up application development with data bind...SE2016 Android Mikle Anokhin "Speed up application development with data bind...
SE2016 Android Mikle Anokhin "Speed up application development with data bind...
 

Mais de Fabio Collini

Architectures in the compose world
Architectures in the compose worldArchitectures in the compose world
Architectures in the compose worldFabio Collini
 
Using hilt in a modularized project
Using hilt in a modularized projectUsing hilt in a modularized project
Using hilt in a modularized projectFabio Collini
 
Managing parallelism using coroutines
Managing parallelism using coroutinesManaging parallelism using coroutines
Managing parallelism using coroutinesFabio Collini
 
Kotlin Delegates in practice - Kotlin community conf
Kotlin Delegates in practice - Kotlin community confKotlin Delegates in practice - Kotlin community conf
Kotlin Delegates in practice - Kotlin community confFabio Collini
 
Kotlin delegates in practice - Kotlin Everywhere Stockholm
Kotlin delegates in practice - Kotlin Everywhere StockholmKotlin delegates in practice - Kotlin Everywhere Stockholm
Kotlin delegates in practice - Kotlin Everywhere StockholmFabio Collini
 
Using Dagger in a Clean Architecture project
Using Dagger in a Clean Architecture projectUsing Dagger in a Clean Architecture project
Using Dagger in a Clean Architecture projectFabio Collini
 
Solid principles in practice the clean architecture - Droidcon Italy
Solid principles in practice the clean architecture - Droidcon ItalySolid principles in practice the clean architecture - Droidcon Italy
Solid principles in practice the clean architecture - Droidcon ItalyFabio Collini
 
SOLID principles in practice: the Clean Architecture - Devfest Emila Romagna
SOLID principles in practice: the Clean Architecture - Devfest Emila RomagnaSOLID principles in practice: the Clean Architecture - Devfest Emila Romagna
SOLID principles in practice: the Clean Architecture - Devfest Emila RomagnaFabio Collini
 
SOLID principles in practice: the Clean Architecture
SOLID principles in practice: the Clean ArchitectureSOLID principles in practice: the Clean Architecture
SOLID principles in practice: the Clean ArchitectureFabio Collini
 
From Java to Kotlin beyond alt+shift+cmd+k - Kotlin Community Conf Milan
From Java to Kotlin beyond alt+shift+cmd+k - Kotlin Community Conf MilanFrom Java to Kotlin beyond alt+shift+cmd+k - Kotlin Community Conf Milan
From Java to Kotlin beyond alt+shift+cmd+k - Kotlin Community Conf MilanFabio Collini
 
Async code on kotlin: rx java or/and coroutines - Kotlin Night Turin
Async code on kotlin: rx java or/and coroutines - Kotlin Night TurinAsync code on kotlin: rx java or/and coroutines - Kotlin Night Turin
Async code on kotlin: rx java or/and coroutines - Kotlin Night TurinFabio Collini
 
Recap Google I/O 2018
Recap Google I/O 2018Recap Google I/O 2018
Recap Google I/O 2018Fabio Collini
 
From java to kotlin beyond alt+shift+cmd+k - Droidcon italy
From java to kotlin beyond alt+shift+cmd+k - Droidcon italyFrom java to kotlin beyond alt+shift+cmd+k - Droidcon italy
From java to kotlin beyond alt+shift+cmd+k - Droidcon italyFabio Collini
 
From java to kotlin beyond alt+shift+cmd+k
From java to kotlin beyond alt+shift+cmd+kFrom java to kotlin beyond alt+shift+cmd+k
From java to kotlin beyond alt+shift+cmd+kFabio Collini
 
Testing Android apps based on Dagger and RxJava Droidcon UK
Testing Android apps based on Dagger and RxJava Droidcon UKTesting Android apps based on Dagger and RxJava Droidcon UK
Testing Android apps based on Dagger and RxJava Droidcon UKFabio Collini
 
Intro to Retrofit 2 and RxJava2
Intro to Retrofit 2 and RxJava2Intro to Retrofit 2 and RxJava2
Intro to Retrofit 2 and RxJava2Fabio Collini
 
Testing Android apps based on Dagger and RxJava
Testing Android apps based on Dagger and RxJavaTesting Android apps based on Dagger and RxJava
Testing Android apps based on Dagger and RxJavaFabio Collini
 

Mais de Fabio Collini (17)

Architectures in the compose world
Architectures in the compose worldArchitectures in the compose world
Architectures in the compose world
 
Using hilt in a modularized project
Using hilt in a modularized projectUsing hilt in a modularized project
Using hilt in a modularized project
 
Managing parallelism using coroutines
Managing parallelism using coroutinesManaging parallelism using coroutines
Managing parallelism using coroutines
 
Kotlin Delegates in practice - Kotlin community conf
Kotlin Delegates in practice - Kotlin community confKotlin Delegates in practice - Kotlin community conf
Kotlin Delegates in practice - Kotlin community conf
 
Kotlin delegates in practice - Kotlin Everywhere Stockholm
Kotlin delegates in practice - Kotlin Everywhere StockholmKotlin delegates in practice - Kotlin Everywhere Stockholm
Kotlin delegates in practice - Kotlin Everywhere Stockholm
 
Using Dagger in a Clean Architecture project
Using Dagger in a Clean Architecture projectUsing Dagger in a Clean Architecture project
Using Dagger in a Clean Architecture project
 
Solid principles in practice the clean architecture - Droidcon Italy
Solid principles in practice the clean architecture - Droidcon ItalySolid principles in practice the clean architecture - Droidcon Italy
Solid principles in practice the clean architecture - Droidcon Italy
 
SOLID principles in practice: the Clean Architecture - Devfest Emila Romagna
SOLID principles in practice: the Clean Architecture - Devfest Emila RomagnaSOLID principles in practice: the Clean Architecture - Devfest Emila Romagna
SOLID principles in practice: the Clean Architecture - Devfest Emila Romagna
 
SOLID principles in practice: the Clean Architecture
SOLID principles in practice: the Clean ArchitectureSOLID principles in practice: the Clean Architecture
SOLID principles in practice: the Clean Architecture
 
From Java to Kotlin beyond alt+shift+cmd+k - Kotlin Community Conf Milan
From Java to Kotlin beyond alt+shift+cmd+k - Kotlin Community Conf MilanFrom Java to Kotlin beyond alt+shift+cmd+k - Kotlin Community Conf Milan
From Java to Kotlin beyond alt+shift+cmd+k - Kotlin Community Conf Milan
 
Async code on kotlin: rx java or/and coroutines - Kotlin Night Turin
Async code on kotlin: rx java or/and coroutines - Kotlin Night TurinAsync code on kotlin: rx java or/and coroutines - Kotlin Night Turin
Async code on kotlin: rx java or/and coroutines - Kotlin Night Turin
 
Recap Google I/O 2018
Recap Google I/O 2018Recap Google I/O 2018
Recap Google I/O 2018
 
From java to kotlin beyond alt+shift+cmd+k - Droidcon italy
From java to kotlin beyond alt+shift+cmd+k - Droidcon italyFrom java to kotlin beyond alt+shift+cmd+k - Droidcon italy
From java to kotlin beyond alt+shift+cmd+k - Droidcon italy
 
From java to kotlin beyond alt+shift+cmd+k
From java to kotlin beyond alt+shift+cmd+kFrom java to kotlin beyond alt+shift+cmd+k
From java to kotlin beyond alt+shift+cmd+k
 
Testing Android apps based on Dagger and RxJava Droidcon UK
Testing Android apps based on Dagger and RxJava Droidcon UKTesting Android apps based on Dagger and RxJava Droidcon UK
Testing Android apps based on Dagger and RxJava Droidcon UK
 
Intro to Retrofit 2 and RxJava2
Intro to Retrofit 2 and RxJava2Intro to Retrofit 2 and RxJava2
Intro to Retrofit 2 and RxJava2
 
Testing Android apps based on Dagger and RxJava
Testing Android apps based on Dagger and RxJavaTesting Android apps based on Dagger and RxJava
Testing Android apps based on Dagger and RxJava
 

Último

哪里有卖的《俄亥俄大学学历证书+俄亥俄大学文凭证书+俄亥俄大学学位证书》Q微信741003700《俄亥俄大学学位证书复制》办理俄亥俄大学毕业证成绩单|购买...
哪里有卖的《俄亥俄大学学历证书+俄亥俄大学文凭证书+俄亥俄大学学位证书》Q微信741003700《俄亥俄大学学位证书复制》办理俄亥俄大学毕业证成绩单|购买...哪里有卖的《俄亥俄大学学历证书+俄亥俄大学文凭证书+俄亥俄大学学位证书》Q微信741003700《俄亥俄大学学位证书复制》办理俄亥俄大学毕业证成绩单|购买...
哪里有卖的《俄亥俄大学学历证书+俄亥俄大学文凭证书+俄亥俄大学学位证书》Q微信741003700《俄亥俄大学学位证书复制》办理俄亥俄大学毕业证成绩单|购买...wyqazy
 
Call US Pooja 9892124323 ✓Call Girls In Mira Road ( Mumbai ) secure service,
Call US Pooja 9892124323 ✓Call Girls In Mira Road ( Mumbai ) secure service,Call US Pooja 9892124323 ✓Call Girls In Mira Road ( Mumbai ) secure service,
Call US Pooja 9892124323 ✓Call Girls In Mira Road ( Mumbai ) secure service,Pooja Nehwal
 
Model Call Girl in Shalimar Bagh Delhi reach out to us at 🔝8264348440🔝
Model Call Girl in Shalimar Bagh Delhi reach out to us at 🔝8264348440🔝Model Call Girl in Shalimar Bagh Delhi reach out to us at 🔝8264348440🔝
Model Call Girl in Shalimar Bagh Delhi reach out to us at 🔝8264348440🔝soniya singh
 
CALL ON ➥8923113531 🔝Call Girls Gomti Nagar Lucknow best Night Fun service
CALL ON ➥8923113531 🔝Call Girls Gomti Nagar Lucknow best Night Fun serviceCALL ON ➥8923113531 🔝Call Girls Gomti Nagar Lucknow best Night Fun service
CALL ON ➥8923113531 🔝Call Girls Gomti Nagar Lucknow best Night Fun serviceanilsa9823
 
CALL ON ➥8923113531 🔝Call Girls Saharaganj Lucknow best sexual service
CALL ON ➥8923113531 🔝Call Girls Saharaganj Lucknow best sexual serviceCALL ON ➥8923113531 🔝Call Girls Saharaganj Lucknow best sexual service
CALL ON ➥8923113531 🔝Call Girls Saharaganj Lucknow best sexual serviceanilsa9823
 
Powerful Love Spells in Arkansas, AR (310) 882-6330 Bring Back Lost Lover
Powerful Love Spells in Arkansas, AR (310) 882-6330 Bring Back Lost LoverPowerful Love Spells in Arkansas, AR (310) 882-6330 Bring Back Lost Lover
Powerful Love Spells in Arkansas, AR (310) 882-6330 Bring Back Lost LoverPsychicRuben LoveSpells
 
9892124323 | Book Call Girls in Juhu and escort services 24x7
9892124323 | Book Call Girls in Juhu and escort services 24x79892124323 | Book Call Girls in Juhu and escort services 24x7
9892124323 | Book Call Girls in Juhu and escort services 24x7Pooja Nehwal
 
Chandigarh Call Girls Service ❤️🍑 9115573837 👄🫦Independent Escort Service Cha...
Chandigarh Call Girls Service ❤️🍑 9115573837 👄🫦Independent Escort Service Cha...Chandigarh Call Girls Service ❤️🍑 9115573837 👄🫦Independent Escort Service Cha...
Chandigarh Call Girls Service ❤️🍑 9115573837 👄🫦Independent Escort Service Cha...Niamh verma
 

Último (8)

哪里有卖的《俄亥俄大学学历证书+俄亥俄大学文凭证书+俄亥俄大学学位证书》Q微信741003700《俄亥俄大学学位证书复制》办理俄亥俄大学毕业证成绩单|购买...
哪里有卖的《俄亥俄大学学历证书+俄亥俄大学文凭证书+俄亥俄大学学位证书》Q微信741003700《俄亥俄大学学位证书复制》办理俄亥俄大学毕业证成绩单|购买...哪里有卖的《俄亥俄大学学历证书+俄亥俄大学文凭证书+俄亥俄大学学位证书》Q微信741003700《俄亥俄大学学位证书复制》办理俄亥俄大学毕业证成绩单|购买...
哪里有卖的《俄亥俄大学学历证书+俄亥俄大学文凭证书+俄亥俄大学学位证书》Q微信741003700《俄亥俄大学学位证书复制》办理俄亥俄大学毕业证成绩单|购买...
 
Call US Pooja 9892124323 ✓Call Girls In Mira Road ( Mumbai ) secure service,
Call US Pooja 9892124323 ✓Call Girls In Mira Road ( Mumbai ) secure service,Call US Pooja 9892124323 ✓Call Girls In Mira Road ( Mumbai ) secure service,
Call US Pooja 9892124323 ✓Call Girls In Mira Road ( Mumbai ) secure service,
 
Model Call Girl in Shalimar Bagh Delhi reach out to us at 🔝8264348440🔝
Model Call Girl in Shalimar Bagh Delhi reach out to us at 🔝8264348440🔝Model Call Girl in Shalimar Bagh Delhi reach out to us at 🔝8264348440🔝
Model Call Girl in Shalimar Bagh Delhi reach out to us at 🔝8264348440🔝
 
CALL ON ➥8923113531 🔝Call Girls Gomti Nagar Lucknow best Night Fun service
CALL ON ➥8923113531 🔝Call Girls Gomti Nagar Lucknow best Night Fun serviceCALL ON ➥8923113531 🔝Call Girls Gomti Nagar Lucknow best Night Fun service
CALL ON ➥8923113531 🔝Call Girls Gomti Nagar Lucknow best Night Fun service
 
CALL ON ➥8923113531 🔝Call Girls Saharaganj Lucknow best sexual service
CALL ON ➥8923113531 🔝Call Girls Saharaganj Lucknow best sexual serviceCALL ON ➥8923113531 🔝Call Girls Saharaganj Lucknow best sexual service
CALL ON ➥8923113531 🔝Call Girls Saharaganj Lucknow best sexual service
 
Powerful Love Spells in Arkansas, AR (310) 882-6330 Bring Back Lost Lover
Powerful Love Spells in Arkansas, AR (310) 882-6330 Bring Back Lost LoverPowerful Love Spells in Arkansas, AR (310) 882-6330 Bring Back Lost Lover
Powerful Love Spells in Arkansas, AR (310) 882-6330 Bring Back Lost Lover
 
9892124323 | Book Call Girls in Juhu and escort services 24x7
9892124323 | Book Call Girls in Juhu and escort services 24x79892124323 | Book Call Girls in Juhu and escort services 24x7
9892124323 | Book Call Girls in Juhu and escort services 24x7
 
Chandigarh Call Girls Service ❤️🍑 9115573837 👄🫦Independent Escort Service Cha...
Chandigarh Call Girls Service ❤️🍑 9115573837 👄🫦Independent Escort Service Cha...Chandigarh Call Girls Service ❤️🍑 9115573837 👄🫦Independent Escort Service Cha...
Chandigarh Call Girls Service ❤️🍑 9115573837 👄🫦Independent Escort Service Cha...
 

Data Binding in Action using MVVM pattern

  • 1. Android Data Binding in action using MVVM pattern Fabio Collini
  • 3. 3 Agenda 1. Data Binding basics 2. Custom attributes 3. Components 4. Two Way Data Binding 5. Model View ViewModel
  • 5. 5 match_result.xml <?xml version="1.0" encoding="utf-8"?>
 <LinearLayout style="@style/root_layout"
 xmlns:android=“http://schemas.android.com/apk/res/android"> 
 <ImageView android:id="@+id/result_gif" style="@style/gif"/>
 
 <LinearLayout style="@style/team_layout">
 <TextView android:id="@+id/home_team" style="@style/name"/>
 <TextView android:id="@+id/home_goals" style="@style/goals"/>
 </LinearLayout>
 
 <LinearLayout style="@style/team_layout">
 <TextView android:id="@+id/away_team" style="@style/name"/>
 <TextView android:id="@+id/away_goals" style="@style/goals"/>
 </LinearLayout>
 </LinearLayout>
  • 6. 6 public class TeamScore {
 private final String name;
 private final int goals; //constructor and getters
 } public class MatchResult {
 private final TeamScore homeTeam;
 private final TeamScore awayTeam;
 private final String gifUrl; //constructor and getters
 }
  • 7. 7 Butterknife Activity @Bind(R.id.result_gif) ImageView resultGif;
 @Bind(R.id.home_team) TextView homeTeam;
 @Bind(R.id.away_team) TextView awayTeam;
 @Bind(R.id.home_goals) TextView homeGoals;
 @Bind(R.id.away_goals) TextView awayGoals;
 
 @Override protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 setContentView(R.layout.match_result);
 ButterKnife.bind(this);
 updateDetail(getIntent().getParcelableExtra("RESULT"));
 }
 private void updateDetail(MatchResult result) {
 Glide.with(this).load(result.getGifUrl())
 .placeholder(R.drawable.loading).into(resultGif);
 if (result.getHomeTeam() != null) {
 homeTeam.setText(result.getHomeTeam().getName());
 homeGoals.setText(Integer.toString(result.getHomeTeam().getGoals()));
 }
 if (result.getAwayTeam() != null) {
 awayTeam.setText(result.getAwayTeam().getName());
 awayGoals.setText(Integer.toString(result.getAwayTeam().getGoals()));
 }
 }
  • 8. DroidCon Italy - Torino - April 2016 - @fabioCollini 8 1Data Binding basics
  • 10. 10 Is Data Binding still beta?
  • 11. 11 Is Data Binding still beta?
  • 12. dataBinding {
 enabled = true
 }
 12 build.gradle android {
 compileSdkVersion 23
 buildToolsVersion "23.0.2"
 
 defaultConfig {
 //...
 ____}
 buildTypes {
 //...
 ____} }
  • 13. <?xml version="1.0" encoding="utf-8"?>
 <layout>
 <LinearLayout style=“@style/root_layout" xmlns:android="http://schemas.android.com/apk/res/android">
 
 <ImageView android:id="@+id/result_gif" style="@style/gif"/>
 
 <LinearLayout style="@style/team_layout">
 <TextView android:id="@+id/home_team" style="@style/name"/>
 <TextView android:id="@+id/home_goals" style="@style/goals"/>
 </LinearLayout>
 
 <LinearLayout style="@style/team_layout">
 <TextView android:id="@+id/away_team" style="@style/name"/>
 <TextView android:id="@+id/away_goals" style="@style/goals"/>
 </LinearLayout>
 </LinearLayout>
 </layout> 13 Data Binding layout <LinearLayout style="@style/root_layout"
 xmlns:android=“http://schemas.android.com/apk/res/android"> 
 <ImageView android:id="@+id/result_gif" style="@style/gif"/>
 
 <LinearLayout style="@style/team_layout">
 <TextView android:id="@+id/home_team" style="@style/name"/>
 <TextView android:id="@+id/home_goals" style="@style/goals"/>
 </LinearLayout>
 
 <LinearLayout style="@style/team_layout">
 <TextView android:id="@+id/away_team" style="@style/name"/>
 <TextView android:id="@+id/away_goals" style="@style/goals"/>
 </LinearLayout>
 </LinearLayout> <?xml version="1.0" encoding="utf-8"?> <layout> </layout>
  • 14. <LinearLayout style="@style/root_layout"
 xmlns:android=“http://schemas.android.com/apk/res/android"> 
 <ImageView android:id="@+id/result_gif" style="@style/gif"/>
 
 <LinearLayout style="@style/team_layout">
 <TextView android:id="@+id/home_team" style="@style/name"/>
 <TextView android:id="@+id/home_goals" style="@style/goals"/>
 </LinearLayout>
 
 <LinearLayout style="@style/team_layout">
 <TextView android:id="@+id/away_team" style="@style/name"/>
 <TextView android:id="@+id/away_goals" style="@style/goals"/>
 </LinearLayout>
 </LinearLayout> 14 One layout traversal match_result.xmlMatchResultBinding.java Auto generated class <?xml version="1.0" encoding="utf-8"?> <layout> </layout> public class MatchResultBinding extends android.databinding.ViewDataBinding {
 
 // ...
 public final android.widget.ImageView resultGif;
 public final android.widget.TextView homeTeam;
 public final android.widget.TextView homeGoals;
 public final android.widget.TextView awayTeam;
 public final android.widget.TextView awayGoals;
 // ...
 }
  • 15. 15 Activity 
 @Override protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 binding = DataBindingUtil.setContentView(this, R.layout.match_result); updateDetail(getIntent().getParcelableExtra("RESULT"));
 }____ 
 private void updateDetail(MatchResult result) {
 Glide.with(this).load(result.getGifUrl())
 .placeholder(R.drawable.loading).into(binding.resultGif);
 if (result.getHomeTeam() != null) {
 binding.homeTeam.setText(result.getHomeTeam().getName());
 binding.homeGoals.setText(Integer.toString(result.getHomeTeam().getGoals()));
 }___
 if (result.getAwayTeam() != null) {
 binding.awayTeam.setText(result.getAwayTeam().getName());
 binding.awayGoals.setText(Integer.toString(result.getAwayTeam().getGoals()));
 }__
 }_ private MatchResultBinding binding;__
  • 16. 16 Variable in layout <?xml version="1.0" encoding="utf-8"?>
 <layout xmlns:android="http://schemas.android.com/apk/res/android"> Automatic null check <data>
 <variable name="result" type="it.droidcon.databinding.MatchResult"/>
 </data> <LinearLayout style="@style/root_layout">
 <ImageView android:id="@+id/result_gif" style="@style/gif"/>
 
 <LinearLayout style="@style/team_layout">
 <TextView style=“@style/name"
 android:text="@{result.homeTeam.name}"/>
 <TextView style="@style/goals"
 android:text="@{Integer.toString(result.homeTeam.goals)}"/>
 </LinearLayout>
 
 <LinearLayout style="@style/team_layout">
 <TextView style="@style/name"
 android:text="@{result.awayTeam.name}"/>
 <TextView style="@style/goals"
 android:text="@{Integer.toString(result.awayTeam.goals)}"/>
 </LinearLayout>
 </LinearLayout>
 </layout>
  • 17. 17 Activity private MatchResultBinding binding; 
 @Override protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 binding = DataBindingUtil.setContentView(this, R.layout.match_result); updateDetail(getIntent().getParcelableExtra("RESULT"));
 }____ 
 private void updateDetail(MatchResult result) {
 Glide.with(this).load(result.getGifUrl())
 .placeholder(R.drawable.loading).into(binding.resultGif);
 binding.setResult(result); }_
  • 18. 18 Code in XML? Are you serious?!?
  • 19. 19 Complex code in XML is NOT a best practice
  • 20. DroidCon Italy - Torino - April 2016 - @fabioCollini 20 2Custom attributes
  • 21. 21 @BindingAdapter <ImageView android:id="@+id/result_gif" style="@style/gif"/> private void updateDetail(MatchResult result) {
 binding.setResult(result);
 Glide.with(this).load(result.getGifUrl())
 .placeholder(R.drawable.loading).into(binding.resultGif);
 } <ImageView style=“@style/gif" app:imageUrl="@{result.gifUrl}"/> @BindingAdapter("imageUrl")
 public static void loadImage(ImageView view, String url) {
 Glide.with(view.getContext()).load(url)
 .placeholder(R.drawable.loading).into(view);
 }
  • 22. 22 public class MatchResultActivity extends AppCompatActivity {
 
 @Override
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 MatchResultBinding binding =
 DataBindingUtil.setContentView(this, R.layout.match_result);
 MatchResult result = getIntent().getParcelableExtra("RESULT");
 binding.setResult(result);
 }
 }
  • 23. 23 Multiple parameters @BindingAdapter({"imageUrl", "placeholder"})
 public static void loadImage(ImageView view, String url, Drawable placeholder) {
 Glide.with(view.getContext()).load(url)
 .placeholder(placeholder).into(view);
 }
 <ImageView style="@style/gif"
 app:imageUrl="@{result.gifUrl}" app:placeholder="@{@drawable/loading}"/>
  • 24. Annotated methods are static but… @BindingAdapter("something")
 public static void bindSomething(View view, AnyObject b) {
 MyBinding binding = DataBindingUtil.findBinding(view); 
 MyObject myObject = binding.getMyObject();
 //… TextView myTextView = 
 binding.myTextView; //… } Can be any object Get the layout binding Get the connected objects Access to all the views Can be defined anywhere Can be used everywhere Can be any View
  • 25. 25 BindingConversion @BindingConversion
 public static @ColorRes int convertEnumToColor(MyEnum value) {
 switch (value) {
 case VALUE1:
 return R.color.color1;
 case VALUE2:
 return R.color.color2;
 case VALUE3:
 return R.color.color3;
 default:
 return R.color.color4;
 }
 } <TextView
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:textColor="@{myObject.myEnum}"/>
  • 26. @BindingConversion
 public static String convertScoreToString(TeamScore score) {
 return Integer.toString(score.getGoals());
 }___
 <TextView style="@style/goals” android:text="@{result.awayTeam}"/>
 26 BindingConversion & BindingAdapter <TextView style="@style/goals"
 android:text="@{Integer.toString(result.awayTeam.goals)}"/>
  • 27. <TextView style="@style/goals" app:goals="@{result.awayTeam.goals}"/> @BindingAdapter("goals")
 public static void bindGoals(TextView view, int goals) {
 view.setText(Integer.toString(goals));
 }__
 @BindingConversion
 public static String convertScoreToString(TeamScore score) {
 return Integer.toString(score.getGoals());
 }___
 27 BindingConversion & BindingAdapter <TextView style="@style/goals"
 android:text="@{Integer.toString(result.awayTeam.goals)}"/> <TextView style="@style/goals” android:text="@{result.awayTeam}"/>

  • 28. <TextView style="@style/goals" app:goals="@{result.awayTeam.goals}"/> @BindingAdapter("goals")
 public static void bindGoals(TextView view, int goals) {
 view.setText(Integer.toString(goals));
 }__
 @BindingConversion
 public static String convertScoreToString(TeamScore score) {
 return Integer.toString(score.getGoals());
 }___
 <TextView style="@style/goals” android:text="@{result.awayTeam}"/>
 28 BindingConversion & BindingAdapter <TextView style="@style/goals"
 android:text="@{Integer.toString(result.awayTeam.goals)}"/>
  • 30. DroidCon Italy - Torino - April 2016 - @fabioCollini 30 3Components
  • 31. 31 <layout xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:app="http://schemas.android.com/apk/res-auto">
 <data>
 <variable name="result"
 type="it.droidcon.databinding.MatchResult"/>
 </data>
 <LinearLayout style="@style/root_layout">
 <ImageView style="@style/gif" app:imageUrl="@{result.gifUrl}"/>
 
 
 <LinearLayout style="@style/team_layout">
 <TextView style="@style/name"
 android:text="@{result.awayTeam.name}"/>
 <TextView style="@style/goals"
 app:goals="@{result.awayTeam.goals}"/>
 </LinearLayout>
 </LinearLayout>
 </layout> <LinearLayout style="@style/team_layout">
 <TextView style="@style/name"
 android:text="@{result.homeTeam.name}"/>
 <TextView style="@style/goals"
 app:goals="@{result.homeTeam.goals}"/>
 </LinearLayout>
  • 33. </data>
 <LinearLayout style="@style/root_layout">
 <ImageView style="@style/gif" app:imageUrl="@{result.gifUrl}"/>
 
 
 <include layout="@layout/team_detail"/> <include layout="@layout/team_detail"/> </LinearLayout>
 </layout> <layout xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:app="http://schemas.android.com/apk/res-auto">
 <data>
 <variable name="result"
 type=“it.droidcon.databinding.MatchResult"/> 

  • 34. </data>
 <LinearLayout style="@style/root_layout">
 <ImageView style="@style/gif" app:imageUrl="@{result.gifUrl}"/>
 
 
 <layout xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:bind="http://schemas.android.com/tools">
 <data>
 <variable name="result"
 type="it.droidcon.databinding.MatchResult"/>
 <include layout="@layout/team_detail"
 /> <include layout="@layout/team_detail"
 /> </LinearLayout>
 </layout> bind:team="@{result.homeTeam}" bind:team="@{result.awayTeam}"
  • 35. </data>
 <LinearLayout style="@style/root_layout" >
 <ImageView style="@style/gif" app:imageUrl="@{result.gifUrl}"/>
 
 
 android:background="@{backgroundColor ?? @color/color1}" <layout xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:bind="http://schemas.android.com/tools">
 <data>
 <variable name="result"
 type="it.droidcon.databinding.MatchResult"/>
 <include layout="@layout/team_detail"
 /> <include layout="@layout/team_detail"
 /> </LinearLayout>
 </layout> bind:team="@{result.homeTeam}" bind:team="@{result.awayTeam}" <variable name="backgroundColor" type="Integer" />
  • 36. DroidCon Italy - Torino - April 2016 - @fabioCollini 36 4Two Way Data Binding
  • 37. 37
  • 38. 38 public class ContactInfo {
 public String message;
 
 public boolean messageAvailable;
 }__
  • 39. 39 public class ContactInfo {
 public String message;
 
 public boolean messageAvailable;
 }__ <layout xmlns:android="http://schemas.android.com/apk/res/android">
 <data>
 <variable name="info"
 type="it.droidcon.databinding.ContactInfo" />
 </data>
 
 <LinearLayout style="@style/contact_root">
 <EditText
 style="@style/contact_text"
 android:enabled="@{info.messageAvailable}"
 android:text="@{info.message}" />
 
 <Button
 style="@style/contact_button"
 android:enabled="@{info.messageAvailable}"
 android:onClick="send" />
 </LinearLayout>
 </layout>
  • 40. 40 public class ContactInfo {
 public String message;
 
 public boolean messageAvailable;
 }__ public class ContactActivity extends AppCompatActivity {
 private ContactInfo contactInfo;
 private ContactBinding binding;
 
 @Override
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 binding = DataBindingUtil.setContentView(this, R.layout.contact);
 contactInfo = new ContactInfo();
 binding.setInfo(contactInfo);
 
 binding.getRoot().postDelayed(() -> {
 contactInfo.message = "my message";
 contactInfo.messageAvailable = true;
 }, 2000);
 }
 
 public void send(View view) {
 Snackbar.make(binding.getRoot(), contactInfo.message, LENGTH_LONG).show();
 }
 }
  • 41. 41
  • 42. 42 Views are not automatically updated :( package android.databinding;
 
 public interface Observable {
 
 void addOnPropertyChangedCallback( OnPropertyChangedCallback callback);
 
 void removeOnPropertyChangedCallback( OnPropertyChangedCallback callback);
 
 abstract class OnPropertyChangedCallback {
 public abstract void onPropertyChanged( Observable sender, int propertyId);
 }
 }
  • 44. public String getMessage() {
 return message;
 }____
 
 public boolean isMessageAvailable() {
 return messageAvailable;
 }___
 
 public void setMessage(String message) {
 this.message = message;
 
 }__
 
 public void setMessageAvailable(boolean messageAvailable) {
 this.messageAvailable = messageAvailable;
 
 }_
 public class ContactInfo
 private String message;
 
 private boolean messageAvailable;
 44 extends BaseObservable { } notifyPropertyChanged(BR.message); notifyPropertyChanged(BR.messageAvailable); @Bindable @Bindable
  • 45. 45 public class ContactInfo {
 public final ObservableField<String> message = new ObservableField<>();_
 
 public final ObservableBoolean messageAvailable = new ObservableBoolean();_
 }__
  • 46. 46 public class ContactInfo {
 public final ObservableField<String> message = new ObservableField<>();_
 
 public final ObservableBoolean messageAvailable = new ObservableBoolean();_
 }__ public class ContactActivity extends AppCompatActivity {
 private ContactInfo contactInfo;
 private ContactBinding binding;
 
 @Override
 protected void onCreate(Bundle savedInstanceState) {
 super.onCreate(savedInstanceState);
 binding = DataBindingUtil.setContentView(this, R.layout.contact);
 contactInfo = new ContactInfo();
 binding.setInfo(contactInfo);
 
 binding.getRoot().postDelayed(() -> {
 contactInfo.message.set("my message");
 contactInfo.messageAvailable.set(true);
 }, 2000); }___
 
 public void send(View view) {
 Snackbar.make(binding.getRoot(), contactInfo.message.get(), LENGTH_LONG).show();
 }__
 }_
  • 47. <layout xmlns:android="http://schemas.android.com/apk/res/android">
 <data>
 <variable name="info"
 type="it.droidcon.databinding.ContactInfo" />
 </data>
 
 <LinearLayout style="@style/contact_root">
 <EditText
 style="@style/contact_text"
 android:enabled="@{info.messageAvailable}"
 android:text="@{info.message}" />
 
 <Button
 style="@style/contact_button"
 android:enabled="@{info.messageAvailable}"
 android:onClick="send" />
 </LinearLayout>
 </layout> 47 public class ContactInfo {
 public final ObservableField<String> message = new ObservableField<>();_
 
 public final ObservableBoolean messageAvailable = new ObservableBoolean();_
 }__ ObservableField<String> ObservableBoolean ObservableBoolean
  • 48. 48
  • 49. 49 Two way Data Binding @BindingAdapter("binding")
 public static void bindEditText(EditText view, final ObservableString observable) {
 Pair<ObservableString, TextWatcherAdapter> pair = (Pair) view.getTag(R.id.bound_observable);
 if (pair == null || pair.first != observable) {
 if (pair != null)
 view.removeTextChangedListener(pair.second);
 TextWatcherAdapter watcher = new TextWatcherAdapter() {
 @Override public void onTextChanged(CharSequence s, int a, int b, int c) {
 observable.set(s.toString());
 }
 };
 view.setTag(R.id.bound_observable, new Pair<>(observable, watcher));
 view.addTextChangedListener(watcher);
 }
 String newValue = observable.get();
 if (!view.getText().toString().equals(newValue))
 view.setText(newValue);
 }
 medium.com/@fabioCollini/android-data-binding-f9f9d3afc761
  • 50. 50
  • 51. 51 <layout xmlns:android="http://schemas.android.com/apk/res/android">
 <data>
 <variable name="info"
 type="it.droidcon.databinding.ContactInfo" />
 </data>
 
 <LinearLayout style="@style/contact_root">
 <EditText
 style="@style/contact_text"
 android:enabled="@{info.messageAvailable}"
 android:text="@={info.message}" />
 
 <Button
 style="@style/contact_button"
 android:enabled="@{info.messageAvailable}"
 android:onClick="send" />
 </LinearLayout>
 </layout> Two way data binding
  • 52. 52
  • 53. 53
  • 55. DroidCon Italy - Torino - April 2016 - @fabioCollini 55 5MVVM
  • 56. 56 MatchResultViewModel public class MatchResultViewModel { 
 public final ObservableField<MatchResult> result = new ObservableField<>();
 
 public final ObservableBoolean loading = new ObservableBoolean();
 
 public void reload() { loading.set(true);
 reloadInBackground(result -> {
 loading.set(false);
 this.result.set(result);
 });
 }
 }
  • 57. <layout xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:bind="http://schemas.android.com/tools">
 <data>
 <variable name="viewModel"
 type="it.droidcon.databinding.MatchResultViewModel"/>
 </data>
 <LinearLayout style="@style/root_layout">
 <ImageView style="@style/gif" app:imageUrl="@{viewModel.result.gifUrl}"/>
 
 
 <include layout="@layout/team_detail"
 /> <include layout="@layout/team_detail"
 /> </LinearLayout>
 </layout> bind:team="@{viewModel.result.homeTeam}" bind:team="@{viewModel.result.awayTeam}" ObservableField
  • 58. 58 Visibility <FrameLayout style="@style/progress_layout"
 android:visibility= "@{viewModel.loading ? View.VISIBLE : View.GONE}">
 <ProgressBar style="@style/progress"/>
 </FrameLayout> <?xml version="1.0" encoding="utf-8"?>
 <layout xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:app="http://schemas.android.com/apk/res-auto"
 xmlns:bind="http://schemas.android.com/tools">
 <data> <import type="android.view.View"/>
 <variable name="viewModel"
 type="it.droidcon.databinding.MatchResultViewModel"/> </data>
 <FrameLayout style="@style/main_container"> 
 <LinearLayout style="@style/root_layout">
 <!-- ... -->
 </LinearLayout>
 
 
 </FrameLayout>
 </layout>
  • 59. 59 Visibility <FrameLayout style="@style/progress_layout"
 android:visibility= "@{viewModel.loading ? View.VISIBLE : View.GONE}">
 <ProgressBar style="@style/progress"/>
 </FrameLayout> @BindingConversion
 public static int convertBooleanToVisibility(boolean b) {
 return b ? View.VISIBLE : View.GONE;
 }___

  • 60. 60 Visibility <FrameLayout style="@style/progress_layout"
 android:visibility="@{viewModel.loading}">
 <ProgressBar style="@style/progress"/>
 </FrameLayout> @BindingConversion
 public static int convertBooleanToVisibility(boolean b) {
 return b ? View.VISIBLE : View.GONE;
 }___
 @BindingAdapter("visibleOrGone")
 public static void bindVisibleOrGone(View view, boolean b) {
 view.setVisibility(b ? View.VISIBLE : View.GONE);
 }____
  • 61. 61 Visibility <FrameLayout style="@style/progress_layout"
 app:visibleOrGone="@{viewModel.loading}">
 <ProgressBar style="@style/progress"/>
 </FrameLayout> @BindingConversion
 public static int convertBooleanToVisibility(boolean b) {
 return b ? View.VISIBLE : View.GONE;
 }___
 @BindingAdapter("visibleOrGone")
 public static void bindVisibleOrGone(View view, boolean b) {
 view.setVisibility(b ? View.VISIBLE : View.GONE);
 }____ @BindingAdapter("visible")
 public static void bindVisible(View view, boolean b) {
 view.setVisibility(b ? View.VISIBLE : View.INVISIBLE);
 }
  • 62. <LinearLayout style="@style/root_layout"
 android:onClick="@{???}">
 <!-- ... -->
 </LinearLayout>
 62 }___ public class MatchResultViewModel { public final ObservableField<MatchResult> result = new ObservableField<>();
 public final ObservableBoolean loading = new ObservableBoolean();
 public void reload() { loading.set(true);
 reloadInBackground(result -> {
 loading.set(false);
 this.result.set(result);
 });
 }__
  • 63. public final_View.OnClickListener reloadClickListener = new View.OnClickListener() {
 @Override public void onClick(View v) {
 reload();
 }_
 };
 <LinearLayout style="@style/root_layout"
 android:onClick="@{viewModel.reloadClickListener}">
 <!-- ... -->
 </LinearLayout>
 63 }___ public class MatchResultViewModel { public final ObservableField<MatchResult> result = new ObservableField<>();
 public final ObservableBoolean loading = new ObservableBoolean();
 public void reload() { loading.set(true);
 reloadInBackground(result -> {
 loading.set(false);
 this.result.set(result);
 });
 }__
  • 64. <LinearLayout style="@style/root_layout"
 android:onClick="@{viewModel::reload}">
 <!-- ... -->
 </LinearLayout>
 64 }___ public class MatchResultViewModel { public final ObservableField<MatchResult> result = new ObservableField<>();
 public final ObservableBoolean loading = new ObservableBoolean();
 public void reload(View v) { loading.set(true);
 reloadInBackground(result -> {
 loading.set(false);
 this.result.set(result);
 });
 }__
  • 65. <LinearLayout style="@style/root_layout"
 android:onClick="@{v -> viewModel.reload()}">
 <!-- ... -->
 </LinearLayout>
 65 }___ public class MatchResultViewModel { public final ObservableField<MatchResult> result = new ObservableField<>();
 public final ObservableBoolean loading = new ObservableBoolean();
 public void reload() { loading.set(true);
 reloadInBackground(result -> {
 loading.set(false);
 this.result.set(result);
 });
 }__
  • 66. public class MatchResultViewModel { public final ObservableField<MatchResult> result = new ObservableField<>();
 public final ObservableBoolean loading = new ObservableBoolean();
 public void reload() { loading.set(true);
 reloadInBackground(result -> {
 loading.set(false);
 this.result.set(result);
 });
 }__ 66 }___ @BindingAdapter("android:onClick")
 public static void bindOnClick(View view, final Runnable listener) {
 view.setOnClickListener(new View.OnClickListener() {
 @Override public void onClick(View v) {
 listener.run();
 }____
 });
 }___ <LinearLayout style="@style/root_layout"
 android:onClick="@{v -> viewModel.reload()}">
 <!-- ... -->
 </LinearLayout>

  • 67. public class MatchResultViewModel { public final ObservableField<MatchResult> result = new ObservableField<>();
 public final ObservableBoolean loading = new ObservableBoolean();
 public void reload() { loading.set(true);
 reloadInBackground(result -> {
 loading.set(false);
 this.result.set(result);
 });
 }__ <LinearLayout style="@style/root_layout"
 android:onClick="@{viewModel::reload}">
 <!-- ... -->
 </LinearLayout>
 67 }___ @BindingAdapter("android:onClick")
 public static void bindOnClick(View view, final Runnable listener) {
 view.setOnClickListener(new View.OnClickListener() {
 @Override public void onClick(View v) {
 listener.run();
 }____
 });
 }___
  • 68. 68 Final layout <?xml version="1.0" encoding="utf-8"?>
 <layout xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:app="http://schemas.android.com/apk/res-auto"
 xmlns:bind="http://schemas.android.com/tools">
 <data>
 <!-- ... -->
 </data>
 <FrameLayout style="@style/main_container"> 
 <LinearLayout style="@style/root_layout"
 android:onClick=“@{viewModel::reload}”>
 <!-- ... -->
 </LinearLayout>
 
 <FrameLayout style="@style/progress_layout"
 app:visibleOrGone="@{viewModel.loading}">
 <ProgressBar style="@style/progress"/>
 </FrameLayout>
 
 </FrameLayout>
 </layout>
  • 69. 69 public interface Reloadable {
 String getErrorMessage();
 
 void reload();
 }
 <layout xmlns:android="http://schemas.android.com/apk/res/android">
 <data>
 <variable name="reloadable"
 type="it.droidcon.databinding.Reloadable"/>
 </data>
 
 <LinearLayout style="@style/reload_layout">
 <TextView
 style="@style/error_message"
 android:text="@{reloadable.errorMessage}"/>
 
 <Button
 style="@style/reload"
 android:onClick="@{reloadable::reload}"
 android:text="@string/reload"/>
 </LinearLayout>
 </layout>
  • 70. 70 Model View ViewModel View ViewModel Model DataBinding Retained on configuration change Saved in Activity or Fragment state Activity or Fragment
  • 71. 71 github.com/fabioCollini/mv2m Android MVVM lightweight library based on Android Data Binding
  • 72. View ViewModel RetrofitService reload update binding Model View ViewModel RetrofitServiceModel request response binding
  • 76. 76 Data binding You can write all your business logic in an huge xml file ———————————————————————— ————————————
  • 77. Custom attributes Reusable UI code 77 Data binding You can write all your business logic in an huge xml file ———————————————————————— ———————————— Includes UI components MVVM Testable code
  • 78. 78 Thanks for your attention! androidavanzato.it Questions?
  • 79. 79 Links developer.android.com/tools/data-binding/guide.html Is Databinding still beta? - Google plus medium.com/@fabioCollini/android-data-binding-f9f9d3afc761 github.com/fabioCollini/mv2m github.com/commit-non-javisti/CoseNonJavisteAndroidApp halfthought.wordpress.com/2016/03/23/2-way-data-binding-on-android