Databinding
Le Databinding ou liaison de donnée permet de déléguer au framework le fait de remplir des données dans la vue en utilisant des mécanismes de génération de code, afin de limiter le code répétitif.
Databinding dans la RecyclerView
Dans un premier temps, voyons comment utiliser le databinding pour les éléments de la RecyclerView.
Layout
Commençons par le Layout, todo_list_item
, dans lequel nous allons rajouter une balise qui va englober tout notre Layout :
<layout xmlns:android="http://schemas.android.com/apk/res/android">
....
</layout>
(n'oubliez pas de déplacer le XMLNS Android de votre LinearLayout à cette nouvelle balise.
Nous devons ensuite déclarer le contexte de donnée du layout :
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable
name="todo"
type="fr.arsenelapostolet.jetpacktuto.model.Todo" />
</data>
....
</layout>
Ces balises permettent de déclarer que ce Layout possède un contexte de donnée qui dépend d'une variable de la classe Todo et qui s'appelle todo. On va donc pouvoir utiliser cette variable dans les éléments de notre Layout :
...
<TextView
android:id="@+id/name"
style="@style/Title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{todo.title}"></TextView>
<TextView
android:id="@+id/lifespan"
style="@style/Text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{todo.description}"></TextView>
...
En utilise la syntaxe @{variable.champs}
on peut lier des données dans notre Layout.
Adapteur
Voyons maintenant du coté de notre adapteur de liste, TodoListAdapter
, qui doit être légèrement modifié pour supporter la liaison de données.
Tout d'abord, notre classe interne ViewHolder ne va plus détenir une View mais un TodoListItem
, une classe générée par le framework pour opérer notre liaison de donnée.
class TodoViewHolder extends RecyclerView.ViewHolder {
public TodoListItem itemView;
public DogViewHolder(@NonNull TodoListItem binding) {
super(binding.getRoot());
this.itemView = binding;
}
}
Ensuite, dans la méthode onCreateViewHolder
, nos devons légèrement modifier la façon dont on inflate notre View :
public TodoViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
LayoutInflater inflater = LayoutInflater.from(parent.getContext());
TodoListItem view = DataBindingUtil.inflate(inflater, R.layout.todo_list_item, parent, false);
return new DogViewHolder(view);
}
Cela permet de faire appel au mécanisme de Databinding pour inflate notre View.
Enfin, nous allons remplacer le contenu de la méthode onBindViewHolder
par une seule ligne, l'affectation de l'objet du modèle à la liaison de donnée :
public void onBindViewHolder(@NonNull TodoViewHolder holder, int position) {
holder.itemView.setTodo(todoList.get(position));
}
Lier des gestionnaires d'événement
On peut également utiliser le Databinding pour faire des liaisons de gestionnaire d'événements. Faisons ça pour implémenter la navigation au clic d'un élément de la RecyclerView.
...Dans votre contexte de donnée, rajoutez une variable de type OnClickListener
. Il s'agit d'une interface fonctionnelle qui définit un contrat de service pour la gestion d'un événements de clique.
Ensuite dans notre adapteur, dans la méthode onBindViewHolder
, rajoutons le binding en passant une :
holder.itemView.setOnTodoClicked(v -> {
ListFragmentDirections.ActionDetail action = ListFragmentDirections.actionDetail();
action.setDogUuid(Integer.parseInt(todo.getId()));
Navigation.findNavController(v).navigate(action);
});
Databinding dans un Fragment
Dans le Layout, on va fait exactement la même chose :
- Rajouter un élément
layout
à la racine - Rajouter une élément
data
pour le contexte donnée - Dans l'élément
data
, créer avec élémentvariable
avec un nom et comme typeTodo
- Déclarer nos liaisons de données avec la syntaxe
@{ }
Pour le Code Behind du fragment, on va pouvoir supprimer tous nos @BindView
et remplacer le contenu notre méthode onCreateView
:
private FragmentDetailBinding binding;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
this.binding = DataBindingUtil.inflate(inflater, R.layout.fragment_detail, container, false);
return binding.getRoot();
}
No Comments