Índice
Exemplo 1: DataBinding implementa vinculação de texto e eventos de clique
Exemplo 2: Ligação da interface secundária
Exemplo 3. Exemplo de ligação bidirecional
Exemplo 4: use a anotação @bindingAdapter para carregar imagens
1. Introdução ao DataBinding
DataBinding é uma biblioteca para vinculação de dados concisa e eficiente em aplicativos Android. Ele permite que os desenvolvedores vinculem declarativamente os componentes da UI às fontes de dados, atualizando automaticamente os dados na interface e simplificando o processo de escrita de código relacionado à UI.
Definir vinculação de dados
Para usar a vinculação de dados, são necessárias as seguintes configurações:
-
Habilite a vinculação de dados no arquivo build.gradle do módulo do aplicativo:
android {
...
dataBinding {
enabled = true
}
}
2. Adicione tags na parte superior do arquivo de layout <layout>
para agrupar o conteúdo do layout:
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<!-- 布局内容 -->
</layout>
3. Obtenha a instância vinculada em Activity ou Fragment:
// 在 Activity 中通过 setContentView 方法绑定布局
MyLayoutBinding binding = DataBindingUtil.setContentView(this, R.layout.my_layout);
// 在 Fragment 中通过 LayoutInflater 绑定布局
MyLayoutBinding binding = MyLayoutBinding.inflate(inflater, container, false);
expressão de ligação de dados
Você pode usar linguagens de expressão em arquivos de layout para fazer referência a dados vinculados e realizar operações, por exemplo:
-
Faça referência a uma variável ou propriedade de objeto:
<TextView
android:text="@{user.name}"
... />
- Executar chamada de método:
<Button
android:onClick="@{onClickListener.onButtonClick()}"
... />
- Use instruções condicionais e loops:
<TextView
android:text="@{user.isAdult ? `Adult` : `Child`}"
... />
<LinearLayout
android:visibility="@{user.isAdmin ? View.VISIBLE : View.GONE}"
... />
<RecyclerView
app:itemList="@{list}"
... />
Ligação bidirecional
A vinculação bidirecional é um conceito de vinculação de dados que mantém automaticamente a sincronização entre a visualização (UI) e o modelo de dados (Modelo). Quando uma variável muda na visão, o modelo de dados associado também é atualizado; inversamente, quando o valor do modelo de dados muda, a visão é atualizada de acordo.
DataBinding também oferece suporte à ligação bidirecional, que reflete alterações nos componentes da UI para a fonte de dados. @=
A ligação bidirecional pode ser obtida através do símbolo:
<EditText
android:text="@={user.name}"
... />
2. Exemplos
Exemplo 1: DataBinding implementa vinculação de texto e eventos de clique
Atividade principal :
package com.example.databinding2;
import androidx.appcompat.app.AppCompatActivity;
import androidx.databinding.DataBindingUtil;
import android.os.Bundle;
import com.example.databinding2.databinding.ActivityMainBinding;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActivityMainBinding mainBinding = DataBindingUtil.setContentView(this,R.layout.activity_main);
// 利用DataBinding绑定UI文本
Food food = new Food("麻辣烫", (float) 4);
// 利用DataBinding实现点击事件
mainBinding.setOnClickListener(new OnClickListener(this));
mainBinding.setFood(food);
}
}
ContagemInício:
package com.example.databinding2;
public class CountStart {
public static String getStar(float star){
return star +"星";
}
}
Comida:
package com.example.databinding;
public class Food {
public String name;
public float star;
public Food(String name,float star){
this.name = name;
this.star = star;
}
}
OnClickListener:
package com.example.databinding2;
import android.content.Context;
import android.view.View;
import android.widget.Toast;
public class OnClickListener {
private Context mContext;
public OnClickListener(Context context){
mContext = context;
}
public void buttonOnClick(View view){
Toast.makeText(mContext, "点击了提交!", Toast.LENGTH_SHORT).show();
}
}
atividade_principal:
<?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:tools="http://schemas.android.com/tools">
<data>
<!-- 实现设置文本 -->
<import type = "com.example.databinding2.CountStart"/>
<variable
name="Food"
type="com.example.databinding2.Food" />
<!-- 实现点击事件 -->
<variable
name="OnClickListener"
type="com.example.databinding2.OnClickListener" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_begin="365dp" />
<ImageView
android:src="@drawable/img"
android:id="@+id/imageView"
android:layout_width="300dp"
android:layout_height="300dp"
app:layout_constraintBottom_toTopOf="@+id/guideline2"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.497"
tools:srcCompat="@tools:sample/avatars" />
<RatingBar
android:id="@+id/ratingBar"
android:layout_width="244dp"
android:layout_height="54dp"
android:max="5"
android:rating="@{Food.star}"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@+id/guideline2"
app:layout_constraintVertical_bias="0.079" />
<TextView
android:id="@+id/textView"
android:layout_width="129dp"
android:layout_height="28dp"
android:text="@{Food.name}"
android:textSize="20sp"
app:layout_constraintBottom_toTopOf="@+id/ratingBar"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.673"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.917" />
<Button
android:onClick="@{OnClickListener.buttonOnClick}"
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="160dp"
android:text="提交"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.498"
app:layout_constraintStart_toStartOf="parent" />
<TextView
android:id="@+id/textView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{CountStart.getStar(Food.star)}"
android:textSize="25sp"
app:layout_constraintBottom_toTopOf="@+id/button"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/ratingBar" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
construir.gradle:
android {
compileSdk 32
defaultConfig {
applicationId "com.example.databinding"
minSdk 21
targetSdk 32
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
dataBinding {
enabled = true
}
}
resultado da operação:
Exemplo 2: Ligação da interface secundária
atividade_principal:
<?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:tools="http://schemas.android.com/tools">
<data>
<!-- 实现设置文本 -->
<import type = "com.example.databinding2.CountStart"/>
<variable
name="Food"
type="com.example.databinding2.Food" />
<!-- 实现点击事件 -->
<variable
name="OnClickListener"
type="com.example.databinding2.OnClickListener" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<androidx.constraintlayout.widget.Guideline
android:id="@+id/guideline2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_begin="365dp" />
<ImageView
android:src="@drawable/img"
android:id="@+id/imageView"
android:layout_width="300dp"
android:layout_height="300dp"
app:layout_constraintBottom_toTopOf="@+id/guideline2"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.497"
tools:srcCompat="@tools:sample/avatars" />
<TextView
android:id="@+id/textView"
android:layout_width="129dp"
android:layout_height="28dp"
android:text="@{Food.name}"
android:textSize="20sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.673"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<include
app:Food="@{Food}"
app:OnClickListener="@{OnClickListener}"
layout="@layout/sub_main"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.497"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@+id/guideline2"
app:layout_constraintVertical_bias="0.253" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
sub principal:
<?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:tools="http://schemas.android.com/tools">
<data>
<variable
name="Food"
type="com.example.databinding2.Food" />
<!-- 实现点击事件 -->
<variable
name="OnClickListener"
type="com.example.databinding2.OnClickListener" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<RatingBar
android:id="@+id/ratingBar2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:rating="@{Food.star}"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.438"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.065" />
<TextView
android:id="@+id/textView3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="32dp"
android:text="@{Food.name}"
android:textSize="25sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.449"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/ratingBar2" />
<Button
android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="24dp"
android:text="提交"
android:onClick="@{OnClickListener.buttonOnClick}"
android:textSize="20sp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.463"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView3" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
Outros códigos e efeitos de execução são iguais ao Exemplo 1.
Exemplo 3. Exemplo de ligação bidirecional
Atividade principal:
public class MainActivity extends AppCompatActivity {
private ViewModel viewModel;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// 使用DataBindingUtil进行绑定
ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main);
// 初始化ViewModel
viewModel = new ViewModel();
// 设置ViewModel到绑定对象中
binding.setViewModel(viewModel);
}
}
Modelo de visualização:
public class ViewModel extends BaseObservable {
private String inputText;
@Bindable
public String getInputText() {
return inputText;
}
public void setInputText(String inputText) {
this.inputText = inputText;
notifyPropertyChanged(BR.inputText);
}
}
atividade_principal:
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable
name="viewModel"
type="com.example.ViewModel" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<EditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@={viewModel.inputText}" />
<!-- 其他视图 -->
</LinearLayout>
</layout>
Exemplo 4: use a anotação @bindingAdapter para carregar imagens
@BindingAdapter
Anotações são anotações usadas para vincular propriedades e métodos personalizados em DataBinding. Por meio@BindingAdapter
de anotações, podemos definir um método estático no qual várias lógicas personalizadas de ligação de dados são implementadas.
Atividade principal :
package com.example.databinding32;
import androidx.appcompat.app.AppCompatActivity;
import androidx.databinding.DataBindingUtil;
import android.os.Bundle;
import com.example.databinding32.databinding.ActivityMainBinding;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActivityMainBinding mainBinding =DataBindingUtil.setContentView(this,R.layout.activity_main);
mainBinding.setNetworkImage("https://img-home.csdnimg.cn/images/20201124032511.png");
// mainBinding.setLocalImage(R.drawable.ic_launcher_background);
}
}
Adaptador ImageBinding:
package com.example.databinding32;
import android.text.TextUtils;
import android.widget.ImageView;
import androidx.databinding.BindingAdapter;
import com.squareup.picasso.Picasso;
public class ImageBindingAdapter {
// 加载网络图片
@BindingAdapter("image")
public static void setImage(ImageView image,String url){
if (!TextUtils.isEmpty(url)){
Picasso.get()
.load(url)
.placeholder(R.drawable.ic_launcher_background)
.into(image);
}else {
image.setImageResource(R.drawable.ic_launcher_background);
}
}
// 加载本地图片
@BindingAdapter("image")
public static void setImage(ImageView image,int resId){
image.setBackgroundResource(resId);
}
// 如果没有url就加载本地图片
@BindingAdapter(value = {"image","defaultImageResources"},requireAll = false)
public static void setImage(ImageView image,String url,int resId){
if (!TextUtils.isEmpty(url)){
Picasso.get()
.load(url)
.placeholder(R.drawable.ic_launcher_background)
.into(image);
}else {
image.setBackgroundResource(resId);
}
}
}
atividade_principal:
<?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:tools="http://schemas.android.com/tools">
<data>
<variable
name="networkImage"
type="String" />
<variable
name="localImage"
type="int" />
</data>
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<ImageView
android:id="@+id/imageView"
android:layout_width="250dp"
android:layout_height="250dp"
app:image="@{networkImage}"
app:defaultImageResources="@{localImage}"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:srcCompat="@tools:sample/avatars" />
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>
Precauções:
Ao usar @BindingAdapter
anotações, você precisa prestar atenção aos seguintes pontos:
-
Localização da anotação:
@BindingAdapter
as anotações podem ser aplicadas a qualquer método estático. -
Parâmetros do método:
@BindingAdapter
Os métodos geralmente têm dois parâmetros: o objeto de visualização (por exemploTextView
,ImageView
) e o valor da propriedade a ser vinculado (por exemplo, string, recurso de imagem, etc.). O método pode ter qualquer número de parâmetros, mas os dois primeiros parâmetros devem ser o objeto de visualização e os valores de propriedade correspondentes. -
Nomenclatura de métodos: para serem associados a propriedades, os nomes dos métodos geralmente
"set"
começam com seguido do nome da propriedade a ser vinculada. Por exemplo, se você quiser vincularimageUrl
uma propriedade, o método poderá ser nomeadosetImageUrl(ImageView view, String url)
. -
Anotações de parâmetros: quando
@BindingAdapter
um método possui vários parâmetros, outras anotações podem ser usadas para identificar parâmetros diferentes. Por exemplo, você pode usar@BindingAdapter({"imageUrl", "placeholder"})
para especificar que o primeiro parâmetro do método corresponde aoimageUrl
atributo e o segundo parâmetro corresponde aoplaceholder
atributo. -
Nome da propriedade: no arquivo de layout, você pode usar
app:属性名称
o método para definir propriedades de ligação personalizadas. Por exemplo,app:imageUrl="@{viewModel.imageUrl}"
.
3. Resumo
O principal significado do uso do DataBinding é simplificar o processo de vinculação de dados e atualização da IU em aplicativos Android e melhorar a eficiência do desenvolvimento e a legibilidade do código. A seguir estão algumas implicações importantes do uso de DataBinding:
1. Simplifique a estrutura do código: por meio do DataBinding, o arquivo de layout e a fonte de dados podem ser vinculados diretamente, reduzindo assim a necessidade de escrever o tedioso findViewById() e definir manualmente o código de dados. Isso torna o código mais conciso e claro e reduz erros causados pela atualização manual da IU.
2. Reduza exceções de ponteiro nulo: DataBinding usa uma linguagem de expressão segura para nulos para evitar exceções de ponteiro nulo causadas por dados nulos. Ao lidar com valores nulos em expressões, você garante acesso e manipulação segura de dados.
3. Melhorar o desempenho : a vinculação de dados pode realizar vinculação de dados e interface em tempo real. Somente quando os dados mudam, a atualização da interface do usuário será acionada. Em comparação com o método tradicional de atualização manual, pode efetivamente reduzir a atualização desnecessária da interface do usuário e melhorar a eficiência do aplicativo • desempenho e capacidade de resposta.
4. Suporte à ligação bidirecional: DataBinding oferece suporte à ligação bidirecional, ou seja, as modificações do usuário na IU podem ser refletidas na fonte de dados. Isso permite implementar facilmente entrada de formulário, alternância de estado e outras funções sem a necessidade de retornos de chamada ou ouvintes adicionais.
5. Melhorar a legibilidade do código : Usando DataBinding, o código relacionado à UI e a lógica de negócios podem ser separados, tornando a estrutura do código mais clara e melhorando a legibilidade e a manutenção do código. Os desenvolvedores podem se concentrar no processamento de dados e níveis lógicos sem manipular diretamente os elementos da interface.
Resumindo, o uso de DataBinding pode simplificar o processo de vinculação de dados, melhorar o desempenho e a legibilidade do código, reduzir erros e fornecer vinculação de dados mais flexível e funções de vinculação bidirecional. É uma ferramenta poderosa que pode melhorar a eficiência do desenvolvimento de aplicativos Android e a experiência do usuário.
Continua. . . . . .