Adaptörleri bağlama

Bağdaştırıcılar, değerler belirleyin. Örneğin, setText() yöntemini kullanabilirsiniz. Diğer Örneğin, bir etkinlik işleyici ayarlayabilirsiniz. Örneğin, setOnClickListener() yöntemidir.

Veri Bağlama Kitaplığı, bir değer ayarlamak için çağrılan yöntemi belirtmenizi sağlar. kendi bağlama mantığınızı sağlayın ve döndürülen nesnenin türünü kullanabilirsiniz.

Özellik değerlerini ayarlama

Bir sınır değeri değiştiğinde, oluşturulan bağlama sınıfı bir belirleyici çağırmalıdır yöntemini çağırın. Veri Bağlantısı'nın Kitaplık, yöntemi otomatik olarak belirler veya yöntemini kullanabilir veya yöntem seçmek için özel mantık sağlayabilirsiniz.

Otomatik yöntem seçimi

Kitaplık, example adlı bir özellik için yöntemi otomatik olarak bulur Uyumlu türleri bağımsız değişken olarak kabul eden setExample(arg). Ad alanı dikkate alınmaz. Yalnızca özellik adı ve türü kullanılır bu en iyi uygulamadır.

Örneğin, android:text="@{user.name}" ifadesinde kitaplık tarafından döndürülen türü kabul eden bir setText(arg) yöntemi user.getName(). user.getName() döndürme türü String ise kitaplığı, String bağımsız değişkenini kabul eden bir setText() yöntemi arar. Öğe ifade bir int döndürürse, kitaplık bir setText() yöntemini arar int bağımsız değişkenini kabul eder. İfade, doğru türü döndürmelidir. Şunları yapabilirsiniz: gerekirse döndürülen değeri kullanın.

Veri bağlama, belirtilen ada sahip herhangi bir özellik olmasa bile çalışır. Şunları yapabilirsiniz: veri bağlamayı kullanarak herhangi bir belirleyici için özellikler oluşturabilirsiniz. Örneğin, destek sınıf DrawerLayout özellikleri yok ama çok sayıda belirleyici var. Aşağıdaki düzen otomatik olarak setScrimColor(int) ve addDrawerListener(DrawerListener) app:scrimColor ve app:drawerListener için belirleyici olarak yöntemleri özellikleri:

<androidx.drawerlayout.widget.DrawerLayout
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:scrimColor="@{@color/scrim}"
    app:drawerListener="@{fragment.drawerListener}">

Özel bir yöntem adı belirtin

Bazı özelliklerde ad ile eşleşmeyen belirleyiciler var. Böyle durumlarda özelliği, BindingMethods ek açıklaması da yer alır. Ek açıklama bir sınıfla kullanılır ve birden fazla içerebilir BindingMethod ek açıklamaları kullanın. Bağlama yöntemleri, daha fazla bilgi edinin.

Aşağıdaki örnekte android:tint özelliği setImageTintList(ColorStateList) yöntemini kullanın (setTint() yöntemiyle değil):

Kotlin

@BindingMethods(value = [
    BindingMethod(
        type = android.widget.ImageView::class,
        attribute = "android:tint",
        method = "setImageTintList")])

Java

@BindingMethods({
       @BindingMethod(type = "android.widget.ImageView",
                      attribute = "android:tint",
                      method = "setImageTintList"),
})

Genellikle Android çerçeve sınıflarında belirleyicileri yeniden adlandırmanız gerekmez. İlgili içeriği oluşturmak için kullanılan özellikleri, otomatik olarak işleme almak için ad kuralı kullanılarak bulmanız gerekir.

Özel mantık sağlayın

Bazı özellikler için özel bağlama mantığı gerekir. Örneğin, android:paddingLeft özelliği için belirleyicidir. Bunun yerine, setPadding(left, top, right, bottom) yöntemi sağlanır. BindingAdapter ek açıklama, bir öznitelik için belirleyicinin çağrılma şeklini özelleştirmenize olanak tanır.

Android çerçeve sınıflarının özelliklerinde zaten BindingAdapter bulunuyor ek açıklamalar. Aşağıdaki örnekte, paddingLeft özelliği:

Kotlin

@BindingAdapter("android:paddingLeft")
fun setPaddingLeft(view: View, padding: Int) {
    view.setPadding(padding,
                view.getPaddingTop(),
                view.getPaddingRight(),
                view.getPaddingBottom())
}

Java

@BindingAdapter("android:paddingLeft")
public static void setPaddingLeft(View view, int padding) {
  view.setPadding(padding,
                  view.getPaddingTop(),
                  view.getPaddingRight(),
                  view.getPaddingBottom());
}

Parametre türleri önemlidir. İlk parametre, görünümdür. İkinci parametre, ilgili özelliğin bağlama ifadesinde kabul edilen tür.

Bağlama bağdaştırıcıları diğer özelleştirme türleri için de yararlıdır. Örneğin, özel yükleyici, görüntü yüklemek için çalışan iş parçacığından çağrılabilir.

Ayrıca, şu örneği inceleyin:

Kotlin

@BindingAdapter("imageUrl", "error")
fun loadImage(view: ImageView, url: String, error: Drawable) {
    Picasso.get().load(url).error(error).into(view)
}

Java

@BindingAdapter({"imageUrl", "error"})
public static void loadImage(ImageView view, String url, Drawable error) {
  Picasso.get().load(url).error(error).into(view);
}

Bağdaştırıcıyı, aşağıdaki örnekte gösterildiği gibi düzeninizde kullanabilirsiniz. Not @drawable/venueError, uygulamanızdaki bir kaynağa atıfta bulunuyor. Etrafında ise @{} içeren kaynak, onu geçerli bir bağlama ifadesi haline getirir.

<ImageView app:imageUrl="@{venue.imageUrl}" app:error="@{@drawable/venueError}" />

Adaptör, imageUrl ve error ImageView nesnesi, imageUrl bir dizesidir; error ise bir Drawable. Şunu istiyorsanız: özelliklerden herhangi biri ayarlandığında çağrılacak bağdaştırıcıyı ayarlayın, isteğe bağlı requireAll aşağıdaki örnekte gösterildiği gibi false olarak ayarlayın:

Kotlin

@BindingAdapter(value = ["imageUrl", "placeholder"], requireAll = false)
fun setImageUrl(imageView: ImageView, url: String?, placeHolder: Drawable?) {
    if (url == null) {
        imageView.setImageDrawable(placeholder);
    } else {
        MyImageLoader.loadInto(imageView, url, placeholder);
    }
}

Java

@BindingAdapter(value={"imageUrl", "placeholder"}, requireAll=false)
public static void setImageUrl(ImageView imageView, String url, Drawable placeHolder) {
  if (url == null) {
    imageView.setImageDrawable(placeholder);
  } else {
    MyImageLoader.loadInto(imageView, url, placeholder);
  }
}

Bağlama bağdaştırıcısı yöntemleri, işleyicilerindeki eski değerleri alabilir. Yöntem Eski ve yeni değerler alındığında, öncelikle özelliklerin tüm eski değerlerini bildirmelidir. ardından aşağıdaki örnekte gösterildiği gibi yeni değerler yazın:

Kotlin

@BindingAdapter("android:paddingLeft")
fun setPaddingLeft(view: View, oldPadding: Int, newPadding: Int) {
    if (oldPadding != newPadding) {
        view.setPadding(newPadding,
                    view.getPaddingTop(),
                    view.getPaddingRight(),
                    view.getPaddingBottom())
    }
}

Java

@BindingAdapter("android:paddingLeft")
public static void setPaddingLeft(View view, int oldPadding, int newPadding) {
  if (oldPadding != newPadding) {
      view.setPadding(newPadding,
                      view.getPaddingTop(),
                      view.getPaddingRight(),
                      view.getPaddingBottom());
   }
}

Etkinlik işleyiciler, yalnızca tek bir arayüze sahip arayüzlerle veya soyut sınıflarla soyut yöntem, aşağıdaki örnekte gösterildiği gibi:

Kotlin

@BindingAdapter("android:onLayoutChange")
fun setOnLayoutChangeListener(
        view: View,
        oldValue: View.OnLayoutChangeListener?,
        newValue: View.OnLayoutChangeListener?
) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
        if (oldValue != null) {
            view.removeOnLayoutChangeListener(oldValue)
        }
        if (newValue != null) {
            view.addOnLayoutChangeListener(newValue)
        }
    }
}

Java

@BindingAdapter("android:onLayoutChange")
public static void setOnLayoutChangeListener(View view, View.OnLayoutChangeListener oldValue,
       View.OnLayoutChangeListener newValue) {
  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
    if (oldValue != null) {
      view.removeOnLayoutChangeListener(oldValue);
    }
    if (newValue != null) {
      view.addOnLayoutChangeListener(newValue);
    }
  }
}

Bu etkinlik işleyiciyi düzeninizde aşağıdaki gibi kullanın:

<View android:onLayoutChange="@{() -> handler.layoutChanged()}"/>

Bir dinleyicinin birden fazla yöntemi varsa bu yöntem birden çok dinleyiciye bölünmelidir. Örneğin, View.OnAttachStateChangeListener iki yöntem vardır: onViewAttachedToWindow(View) ve onViewDetachedFromWindow(View). Kitaplık, özellikleri ve işleyicileri ayırt etmek için iki arayüz sağlar yararlanabilir:

Kotlin

// Translation from provided interfaces in Java:
@TargetApi(Build.VERSION_CODES.HONEYCOMB_MR1)
interface OnViewDetachedFromWindow {
    fun onViewDetachedFromWindow(v: View)
}

@TargetApi(Build.VERSION_CODES.HONEYCOMB_MR1)
interface OnViewAttachedToWindow {
    fun onViewAttachedToWindow(v: View)
}

Java

@TargetApi(VERSION_CODES.HONEYCOMB_MR1)
public interface OnViewDetachedFromWindow {
  void onViewDetachedFromWindow(View v);
}

@TargetApi(VERSION_CODES.HONEYCOMB_MR1)
public interface OnViewAttachedToWindow {
  void onViewAttachedToWindow(View v);
}

Bir işleyiciyi değiştirmek diğerini etkileyebileceğinden, iki özellik için de kullanılabilir. requireAll değerini şurada false olarak ayarlayabilirsiniz: her özelliğe bir bağlama atanması gerekmediğini belirten ek açıklama aşağıdaki örnekte gösterildiği gibi:

Kotlin

@BindingAdapter(
        "android:onViewDetachedFromWindow",
        "android:onViewAttachedToWindow",
        requireAll = false
)
fun setListener(view: View, detach: OnViewDetachedFromWindow?, attach: OnViewAttachedToWindow?) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR1) {
        val newListener: View.OnAttachStateChangeListener?
        newListener = if (detach == null && attach == null) {
            null
        } else {
            object : View.OnAttachStateChangeListener {
                override fun onViewAttachedToWindow(v: View) {
                    attach.onViewAttachedToWindow(v)
                }

                override fun onViewDetachedFromWindow(v: View) {
                    detach.onViewDetachedFromWindow(v)
                }
            }
        }

        val oldListener: View.OnAttachStateChangeListener? =
                ListenerUtil.trackListener(view, newListener, R.id.onAttachStateChangeListener)
        if (oldListener != null) {
            view.removeOnAttachStateChangeListener(oldListener)
        }
        if (newListener != null) {
            view.addOnAttachStateChangeListener(newListener)
        }
    }
}

Java

@BindingAdapter({"android:onViewDetachedFromWindow", "android:onViewAttachedToWindow"}, requireAll=false)
public static void setListener(View view, OnViewDetachedFromWindow detach, OnViewAttachedToWindow attach) {
    if (VERSION.SDK_INT >= VERSION_CODES.HONEYCOMB_MR1) {
        OnAttachStateChangeListener newListener;
        if (detach == null && attach == null) {
            newListener = null;
        } else {
            newListener = new OnAttachStateChangeListener() {
                @Override
                public void onViewAttachedToWindow(View v) {
                    if (attach != null) {
                        attach.onViewAttachedToWindow(v);
                    }
                }
                @Override
                public void onViewDetachedFromWindow(View v) {
                    if (detach != null) {
                        detach.onViewDetachedFromWindow(v);
                    }
                }
            };
        }

        OnAttachStateChangeListener oldListener = ListenerUtil.trackListener(view, newListener,
                R.id.onAttachStateChangeListener);
        if (oldListener != null) {
            view.removeOnAttachStateChangeListener(oldListener);
        }
        if (newListener != null) {
            view.addOnAttachStateChangeListener(newListener);
        }
    }
}

Yukarıdaki örnek biraz karmaşıktır çünkü View sınıfı şunu kullanır: addOnAttachStateChangeListener() ve removeOnAttachStateChangeListener() bir belirleyici yöntem yerine OnAttachStateChangeListener android.databinding.adapters.ListenerUtil sınıfı bunları takip etmenize yardımcı olur. bağlayıcı adaptöründen çıkarılabilmeleri için işleyicileri oluşturun.

Nesne dönüşümleri

Otomatik nesne dönüştürme

Bir bağlamadan Object döndürüldüğünde ifadesinde kitaplık, Object, seçilen yöntemin parametre türüne dönüştürülür. Bu kullanımı kolay olduğu için ObservableMap sınıfı aşağıdaki örnekte gösterildiği gibi mağaza verileri:

<TextView
   android:text='@{userMap["lastName"]}'
   android:layout_width="wrap_content"
   android:layout_height="wrap_content" />

İfadedeki userMap nesnesi, otomatik olarak çevrim yapmak için kullanılan setText(CharSequence) yönteminde bulunan parametre türüne android:text özelliğinin değerini ayarlayın. Parametre türü belirsizse döndürme türünü ifadeye dönüştürün.

Özel dönüşümler

Bazı durumlarda, belirli türler arasında özel dönüşüm yapılması gerekir. Örneğin, Örneğin, bir görünümün android:background özelliği Drawable bekler, ancak belirtilen color değeri bir tam sayıdır. Aşağıdaki örnekte bir özelliğindeki değer, Drawable bekliyor, ancak bunun yerine bir tam sayı sağlanıyor:

<View
   android:background="@{isError ? @color/red : @color/white}"
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"/>

Drawable beklendiğinde ve bir tam sayı döndürüldüğünde int öğesini dönüştürün bir ColorDrawable olarak ekleyebilirsiniz. Dönüşümü gerçekleştirmek için statik bir yöntem kullanarak BindingConversion ek açıklaması şu şekildedir:

Kotlin

@BindingConversion
fun convertColorToDrawable(color: Int) = ColorDrawable(color)

Java

@BindingConversion
public static ColorDrawable convertColorToDrawable(int color) {
    return new ColorDrawable(color);
}

Ancak bağlama ifadesinde sağlanan değer türleri tutarlı olmalıdır. Aşağıda gösterildiği gibi, aynı ifadede farklı türler kullanamazsınız. örnek:

// The @drawable and @color represent different value types in the same
// expression, which causes a build error.
<View
   android:background="@{isError ? @drawable/error : @color/white}"
   android:layout_width="wrap_content"
   android:layout_height="wrap_content"/>

Ek kaynaklar

Veri bağlama hakkında daha fazla bilgi edinmek için aşağıdaki kaynaklara bakın.

Örnekler

Codelab'ler

Blog yayınları

ziyaret edin. ziyaret edin.