Android
Gegevensbindende bibliotheek
Zoeken…
Opmerkingen
Opstelling
Voordat u gegevensbinding gebruikt, moet u de plug-in in uw build.gradle
.
android {
....
dataBinding {
enabled = true
}
}
Opmerking: gegevensbinding is toegevoegd aan de Android Gradle-plug-in in versie 1.5.0
Bindende klassenamen
De plug-in voor gegevensbinding genereert een naam voor de bindklasse door de bestandsnaam van uw lay-out te converteren naar het geval Pascal en aan het einde "Binding" toe te voegen. Dus item_detail_activity.xml
genereert een klasse met de naam ItemDetailActivityBinding
.
Middelen
Basistekstveld bindend
Gradle (Module: app) Configuratie
android {
....
dataBinding {
enabled = true
}
}
Gegevensmodel
public class Item {
public String name;
public String description;
public Item(String name, String description) {
this.name = name;
this.description = description;
}
}
Lay-out XML
De eerste stap is het verpakken van uw lay-out in een <layout>
-tag, het toevoegen van een <data>
-element en het toevoegen van een <variable>
-element voor uw gegevensmodel.
Vervolgens kunt u XML-kenmerken binden aan velden in het gegevensmodel met behulp van @{model.fieldname}
, waarbij model
de naam van de variabele is en fieldname
het veld @{model.fieldname}
u toegang wilt.
item_detail_activity.xml:
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable name="item" type="com.example.Item"/>
</data>
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{item.name}"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{item.description}"/>
</LinearLayout>
</layout>
Voor elk XML-lay-outbestand dat correct is geconfigureerd met bindingen, genereert de Android Gradle-plug-in een overeenkomstige klasse: bindingen. Omdat we een lay-out hebben met de naam item_detail_activity , wordt de bijbehorende gegenereerde bindende klasse ItemDetailActivityBinding
.
Deze binding kan vervolgens worden gebruikt in een activiteit als volgt:
public class ItemDetailActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ItemDetailActivityBinding binding = DataBindingUtil.setContentView(this, R.layout.item_detail_activity);
Item item = new Item("Example item", "This is an example item.");
binding.setItem(item);
}
}
Binden met een accessormethode
Als uw model privé-methoden heeft, kunt u in de databinding-bibliotheek nog steeds toegang krijgen tot uw weergave zonder de volledige naam van de methode te gebruiken.
Gegevensmodel
public class Item {
private String name;
public String getName() {
return name;
}
}
Lay-out XML
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable name="item" type="com.example.Item"/>
</data>
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- Since the "name" field is private on our data model,
this binding will utilize the public getName() method instead. -->
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{item.name}"/>
</LinearLayout>
</layout>
Verwijzen naar klassen
Gegevensmodel
public class Item {
private String name;
public String getName() {
return name;
}
}
Lay-out XML
U moet klassen waarnaar wordt verwezen, importeren, net als in Java.
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<import type="android.view.View"/>
<variable name="item" type="com.example.Item"/>
</data>
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- We reference the View class to set the visibility of this TextView -->
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{item.name}"
android:visibility="@{item.name == null ? View.VISIBLE : View.GONE"/>
</LinearLayout>
</layout>
Opmerking: het pakket java.lang.*
Wordt automatisch door het systeem geïmporteerd. (Hetzelfde is gemaakt door JVM
voor Java
)
Databinding in fragment
Gegevensmodel
public class Item {
private String name;
public String getName() {
return name;
}
public void setName(String name){
this.name = name;
}
}
Lay-out XML
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable name="item" type="com.example.Item"/>
</data>
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{item.name}"/>
</LinearLayout>
</layout>
Fragment
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
FragmentTest binding = DataBindingUtil.inflate(inflater, R.layout.fragment_test, container, false);
Item item = new Item();
item.setName("Thomas");
binding.setItem(item);
return binding.getRoot();
}
Ingebouwde tweeweg-gegevensbinding
Tweerichtingsbinding ondersteunt de volgende kenmerken:
Element | Eigendommen |
---|---|
AbsListView | android:selectedItemPosition |
CalendarView | android:date |
CompoundButton | android:checked |
DatePicker |
|
EditText | android:text |
NumberPicker | android:value |
RadioGroup | android:checkedButton |
RatingBar | android:rating |
SeekBar | android:progress |
TabHost | android:currentTab |
TextView | android:text |
TimePicker |
|
ToggleButton | android:checked |
Switch | android:checked |
Gebruik
<layout ...>
<data>
<variable type="com.example.myapp.User" name="user"/>
</data>
<RelativeLayout ...>
<EditText android:text="@={user.firstName}" .../>
</RelativeLayout>
</layout>
Merk op dat de bindingsexpressie @={}
een extra =
, die nodig is voor de bidirectionele binding . Het is niet mogelijk om methoden in tweeweg bindende expressies te gebruiken.
Gegevensbinding in RecyclerView Adapter
Het is ook mogelijk om gegevensbinding te gebruiken in uw RecyclerView
adapter.
Gegevensmodel
public class Item {
private String name;
public String getName() {
return name;
}
}
XML-indeling
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{item.name}"/>
Adapterklasse
public class ListItemAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private Activity host;
private List<Item> items;
public ListItemAdapter(Activity activity, List<Item> items) {
this.host = activity;
this.items = items;
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
// inflate layout and retrieve binding
ListItemBinding binding = DataBindingUtil.inflate(host.getLayoutInflater(),
R.layout.list_item, parent, false);
return new ItemViewHolder(binding);
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
Item item = items.get(position);
ItemViewHolder itemViewHolder = (ItemViewHolder)holder;
itemViewHolder.bindItem(item);
}
@Override
public int getItemCount() {
return items.size();
}
private static class ItemViewHolder extends RecyclerView.ViewHolder {
ListItemBinding binding;
ItemViewHolder(ListItemBinding binding) {
super(binding.getRoot());
this.binding = binding;
}
void bindItem(Item item) {
binding.setItem(item);
binding.executePendingBindings();
}
}
}
Klik op luisteraar met binding
Maak een interface voor clickHandler
public interface ClickHandler {
public void onButtonClick(View v);
}
Lay-out XML
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable
name="handler"
type="com.example.ClickHandler"/>
</data>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="click me"
android:onClick="@{handler.onButtonClick}"/>
</RelativeLayout>
</layout>
Behandel gebeurtenis in uw activiteit
public class MainActivity extends Activity implements ClickHandler {
private ActivityMainBinding binding;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = DataBindingUtil.setContentView(this,R.layout.activity_main);
binding.setHandler(this);
}
@Override
public void onButtonClick(View v) {
Toast.makeText(context,"Button clicked",Toast.LENGTH_LONG).show();
}
}
Aangepaste gebeurtenis met lambda-expressie
Definieer Interface
public interface ClickHandler {
public void onButtonClick(User user);
}
Modelklasse maken
public class User {
private String name;
public User(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Lay-out XML
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<variable
name="handler"
type="com.example.ClickHandler"/>
<variable
name="user"
type="com.example.User"/>
</data>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@{user.name}"
android:onClick="@{() -> handler.onButtonClick(user)}"/>
</RelativeLayout>
</layout>
Activiteit code:
public class MainActivity extends Activity implements ClickHandler {
private ActivityMainBinding binding;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = DataBindingUtil.setContentView(this,R.layout.activity_main);
binding.setUser(new User("DataBinding User"));
binding.setHandler(this);
}
@Override
public void onButtonClick(User user) {
Toast.makeText(MainActivity.this,"Welcome " + user.getName(),Toast.LENGTH_LONG).show();
}
}
Voor sommige view-luisteraars die niet beschikbaar zijn in XML-code, maar kunnen worden ingesteld in Java-code, kan deze bindend zijn met aangepaste binding.
Aangepaste klasse
public class BindingUtil {
@BindingAdapter({"bind:autoAdapter"})
public static void setAdapter(AutoCompleteTextView view, ArrayAdapter<String> pArrayAdapter) {
view.setAdapter(pArrayAdapter);
}
@BindingAdapter({"bind:onKeyListener"})
public static void setOnKeyListener(AutoCompleteTextView view , View.OnKeyListener pOnKeyListener)
{
view.setOnKeyListener(pOnKeyListener);
}
}
Handler-klasse
public class Handler extends BaseObservable {
private ArrayAdapter<String> roleAdapter;
public ArrayAdapter<String> getRoleAdapter() {
return roleAdapter;
}
public void setRoleAdapter(ArrayAdapter<String> pRoleAdapter) {
roleAdapter = pRoleAdapter;
}
}
XML
<layout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:bind="http://schemas.android.com/tools" >
<data>
<variable
name="handler"
type="com.example.Handler" />
</data>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<AutoCompleteTextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:singleLine="true"
bind:autoAdapter="@{handler.roleAdapter}" />
</LinearLayout>
</layout>
Standaardwaarde in gegevensbinding
In het voorbeeldvenster worden standaardwaarden voor gegevensbindende expressies weergegeven, indien aanwezig.
Bijvoorbeeld :
android:layout_height="@{@dimen/main_layout_height, default=wrap_content}"
Het zal wrap_content
nemen tijdens het ontwerpen en zal fungeren als een wrap_content
in het voorbeeldvenster.
Een ander voorbeeld is
android:text="@{user.name, default=`Preview Text`}"
Het zal Preview Text
in het voorbeeldvenster, maar wanneer u het in apparaat / emulator uitvoert, wordt de werkelijke tekst die eraan is gekoppeld weergegeven
DataBinding met aangepaste variabelen (int, boolean)
Soms moeten we basisbewerkingen uitvoeren zoals de weergave Verbergen / Weergeven op basis van één waarde, voor die enkele variabele kunnen we geen model maken of het is geen goede gewoonte om daarvoor een model te maken. DataBinding ondersteunt standaard datatypes om die operaties uit te voeren.
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
<import type="android.view.View" />
<variable
name="selected"
type="Boolean" />
</data>
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World"
android:visibility="@{selected ? View.VISIBLE : View.GONE}" />
</RelativeLayout>
</layout>
en stel de waarde in van Java-klasse.
binding.setSelected(true);
Databinding in dialoogvenster
public void doSomething() {
DialogTestBinding binding = DataBindingUtil
.inflate(LayoutInflater.from(context), R.layout.dialog_test, null, false);
Dialog dialog = new Dialog(context);
dialog.setContentView(binding.getRoot());
dialog.show();
}
Geef widget door als referentie in BindingAdapter
Lay-out XML
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android">
<data>
</data>
<LinearLayout
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ProgressBar
android:id="@+id/progressBar"
style="?android:attr/progressBarStyleSmall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<ImageView
android:id="@+id/img"
android:layout_width="match_parent"
android:layout_height="100dp"
app:imageUrl="@{url}"
app:progressbar="@{progressBar}"/>
</LinearLayout>
</layout>
BindingAdapter-methode
@BindingAdapter({"imageUrl","progressbar"})
public static void loadImage(ImageView view, String imageUrl, ProgressBar progressBar){
Glide.with(view.getContext()).load(imageUrl)
.listener(new RequestListener<String, GlideDrawable>() {
@Override
public boolean onException(Exception e, String model, Target<GlideDrawable> target, boolean isFirstResource) {
return false;
}
@Override
public boolean onResourceReady(GlideDrawable resource, String model, Target<GlideDrawable> target, boolean isFromMemoryCache, boolean isFirstResource) {
progressBar.setVisibility(View.GONE);
return false;
}
}).into(view);
}