آداپتورهای اتصال مسئول ایجاد فراخوانی چارچوب مناسب برای تنظیم مقادیر هستند. یک مثال تنظیم یک مقدار ویژگی است، مانند فراخوانی متد setText()
. مثال دیگر تنظیم شنونده رویداد است، مانند فراخوانی متد setOnClickListener()
.
کتابخانه Data Binding به شما امکان می دهد روش فراخوانی شده برای تنظیم یک مقدار را مشخص کنید، منطق صحافی خود را ارائه دهید، و نوع شیء برگشتی را با استفاده از آداپتورها مشخص کنید.
مقادیر مشخصه را تنظیم کنید
هر زمان که یک مقدار کران تغییر کند، کلاس binding تولید شده باید یک متد setter را در view با عبارت binding فراخوانی کند. می توانید اجازه دهید Data Binding Library به طور خودکار روش را تعیین کند، یا می توانید به صراحت روش را اعلام کنید یا منطق سفارشی برای انتخاب یک روش ارائه دهید.
انتخاب روش خودکار
برای مشخصه ای به نام example
، کتابخانه به طور خودکار متد setExample(arg)
را پیدا می کند که انواع سازگار را به عنوان آرگومان می پذیرد. فضای نام ویژگی در نظر گرفته نشده است. هنگام جستجوی یک متد فقط از نام و نوع ویژگی استفاده می شود.
برای مثال، با توجه به عبارت android:text="@{user.name}"
، کتابخانه به دنبال یک متد setText(arg)
میگردد که نوع بازگردانده شده توسط user.getName()
میپذیرد. اگر نوع برگشتی user.getName()
String
باشد، کتابخانه به دنبال متد setText()
می گردد که آرگومان String
می پذیرد. اگر عبارت یک int
برگرداند، کتابخانه متد setText()
را جستجو می کند که آرگومان int
می پذیرد. عبارت باید نوع صحیح را برگرداند. در صورت لزوم می توانید مقدار بازگشتی را ارسال کنید.
اتصال داده حتی اگر هیچ ویژگی با نام داده شده وجود نداشته باشد کار می کند. شما می توانید برای هر تنظیم کننده با استفاده از اتصال داده، ویژگی ایجاد کنید. به عنوان مثال، کلاس پشتیبانی DrawerLayout
ویژگی ندارد، اما تنظیم کننده های زیادی دارد. طرحبندی زیر بهطور خودکار از متدهای setScrimColor(int)
و addDrawerListener(DrawerListener)
بهعنوان تنظیمکننده ویژگیهای app:scrimColor
و app:drawerListener
استفاده میکند:
<androidx.drawerlayout.widget.DrawerLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:scrimColor="@{@color/scrim}"
app:drawerListener="@{fragment.drawerListener}">
نام روش سفارشی را مشخص کنید
برخی از ویژگی ها تنظیم کننده هایی دارند که با نام مطابقت ندارند. در این شرایط، یک ویژگی را می توان با استفاده از حاشیه نویسی BindingMethods
با تنظیم کننده مرتبط کرد. حاشیه نویسی با یک کلاس استفاده می شود و می تواند حاوی چندین حاشیه نویسی BindingMethod
باشد، یکی برای هر روش تغییر نام یافته. روشهای اتصال حاشیهنویسی هستند که میتوانید به هر کلاسی در برنامه خود اضافه کنید.
در مثال زیر، ویژگی android:tint
با متد setImageTintList(ColorStateList)
مرتبط است نه با متد setTint()
:
کاتلین
@BindingMethods(value = [ BindingMethod( type = android.widget.ImageView::class, attribute = "android:tint", method = "setImageTintList")])
جاوا
@BindingMethods({ @BindingMethod(type = "android.widget.ImageView", attribute = "android:tint", method = "setImageTintList"), })
به طور معمول، شما نیازی به تغییر نام ستترها در کلاس های فریمورک اندروید ندارید. ویژگی ها قبلاً با استفاده از قرارداد نام برای یافتن خودکار روش های تطبیق پیاده سازی شده اند.
منطق سفارشی را ارائه دهید
برخی از ویژگی ها به منطق اتصال سفارشی نیاز دارند. برای مثال، هیچ تنظیم کننده مرتبطی برای ویژگی android:paddingLeft
وجود ندارد. در عوض، متد setPadding(left, top, right, bottom)
ارائه شده است. یک روش آداپتور اتصال ایستا با حاشیه نویسی BindingAdapter
به شما امکان می دهد نحوه فراخوانی یک تنظیم کننده برای یک ویژگی را سفارشی کنید.
ویژگیهای کلاسهای فریمورک اندروید از قبل دارای حاشیهنویسی BindingAdapter
هستند. مثال زیر آداپتور binding برای ویژگی paddingLeft
را نشان می دهد:
کاتلین
@BindingAdapter("android:paddingLeft") fun setPaddingLeft(view: View, padding: Int) { view.setPadding(padding, view.getPaddingTop(), view.getPaddingRight(), view.getPaddingBottom()) }
جاوا
@BindingAdapter("android:paddingLeft") public static void setPaddingLeft(View view, int padding) { view.setPadding(padding, view.getPaddingTop(), view.getPaddingRight(), view.getPaddingBottom()); }
انواع پارامترها مهم هستند. پارامتر اول نوع نمای مرتبط با ویژگی را تعیین می کند. پارامتر دوم نوع پذیرفته شده در عبارت binding برای ویژگی داده شده را تعیین می کند.
آداپتورهای اتصال برای انواع دیگر سفارشی سازی نیز مفید هستند. به عنوان مثال، یک لودر سفارشی را می توان از یک موضوع کارگر برای بارگذاری یک تصویر فراخوانی کرد.
همچنین می توانید آداپتورهایی داشته باشید که چندین ویژگی دریافت می کنند، همانطور که در مثال زیر نشان داده شده است:
کاتلین
@BindingAdapter("imageUrl", "error") fun loadImage(view: ImageView, url: String, error: Drawable) { Picasso.get().load(url).error(error).into(view) }
جاوا
@BindingAdapter({"imageUrl", "error"}) public static void loadImage(ImageView view, String url, Drawable error) { Picasso.get().load(url).error(error).into(view); }
همانطور که در مثال زیر نشان داده شده است می توانید از آداپتور در طرح بندی خود استفاده کنید. توجه داشته باشید که @drawable/venueError
به منبعی در برنامه شما اشاره دارد. احاطه کردن منبع با @{}
آن را به یک عبارت الزام آور معتبر تبدیل می کند.
<ImageView app:imageUrl="@{venue.imageUrl}" app:error="@{@drawable/venueError}" />
اگر imageUrl
و error
برای یک شی ImageView
استفاده شود، imageUrl
یک رشته و error
یک Drawable
باشد، آداپتور فراخوانی می شود. اگر می خواهید زمانی که هر یک از ویژگی ها تنظیم شده است، آداپتور فراخوانی شود، همانطور که در مثال زیر نشان داده شده است، پرچم اختیاری requireAll
آداپتور را روی false
قرار دهید:
کاتلین
@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); } }
جاوا
@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); } }
روشهای آداپتور اتصال میتوانند مقادیر قدیمی را در گردانندههای خود بگیرند. روشی که مقادیر قدیمی و جدید را دریافت می کند باید ابتدا همه مقادیر قدیمی را برای ویژگی ها و سپس مقادیر جدید را اعلام کند، همانطور که در مثال زیر نشان داده شده است:
کاتلین
@BindingAdapter("android:paddingLeft") fun setPaddingLeft(view: View, oldPadding: Int, newPadding: Int) { if (oldPadding != newPadding) { view.setPadding(newPadding, view.getPaddingTop(), view.getPaddingRight(), view.getPaddingBottom()) } }
جاوا
@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()); } }
کنترلکنندههای رویداد فقط میتوانند با رابطها یا کلاسهای انتزاعی با یک متد انتزاعی استفاده شوند، همانطور که در مثال زیر نشان داده شده است:
کاتلین
@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) } } }
جاوا
@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); } } }
از این کنترل کننده رویداد در طرح بندی خود به صورت زیر استفاده کنید:
<View android:onLayoutChange="@{() -> handler.layoutChanged()}"/>
وقتی یک شنونده چندین روش دارد، باید به چندین شنونده تقسیم شود. برای مثال، View.OnAttachStateChangeListener
دو روش دارد: onViewAttachedToWindow(View)
و onViewDetachedFromWindow(View)
. این کتابخانه دو رابط برای متمایز کردن ویژگی ها و کنترل کننده ها برای آنها فراهم می کند:
کاتلین
// 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) }
جاوا
@TargetApi(VERSION_CODES.HONEYCOMB_MR1) public interface OnViewDetachedFromWindow { void onViewDetachedFromWindow(View v); } @TargetApi(VERSION_CODES.HONEYCOMB_MR1) public interface OnViewAttachedToWindow { void onViewAttachedToWindow(View v); }
از آنجا که تغییر یک شنونده می تواند بر دیگری تأثیر بگذارد، شما به آداپتوری نیاز دارید که برای هر کدام از ویژگی ها یا برای هر دو کار کند. همانطور که در مثال زیر نشان داده شده است، میتوانید requireAll
در حاشیهنویسی روی false
تنظیم کنید تا مشخص کنید که نباید به هر ویژگی یک عبارت binding اختصاص داده شود:
کاتلین
@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) } } }
جاوا
@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); } } }
مثال بالا کمی پیچیده است زیرا کلاس View
از متدهای addOnAttachStateChangeListener()
و removeOnAttachStateChangeListener()
به جای متد تنظیم کننده برای OnAttachStateChangeListener
استفاده می کند. کلاس android.databinding.adapters.ListenerUtil
به پیگیری این شنوندگان کمک می کند تا بتوان آنها را در آداپتور binding حذف کرد.
تبدیل شی
تبدیل خودکار شی
هنگامی که یک Object
از یک عبارت binding برگردانده می شود، کتابخانه روش مورد استفاده برای تنظیم مقدار ویژگی را انتخاب می کند. Object
به یک نوع پارامتر از روش انتخاب شده فرستاده می شود. این رفتار در برنامه هایی که از کلاس ObservableMap
برای ذخیره داده ها استفاده می کنند، راحت است، همانطور که در مثال زیر نشان داده شده است:
<TextView
android:text='@{userMap["lastName"]}'
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
شی userMap
در عبارت، مقداری را برمی گرداند، که به طور خودکار به نوع پارامتر موجود در متد setText(CharSequence)
که برای تنظیم مقدار مشخصه android:text
استفاده می شود، فرستاده می شود. اگر نوع پارامتر مبهم است، نوع بازگشتی را در عبارت وارد کنید.
تبدیل های سفارشی
در برخی شرایط، یک تبدیل سفارشی بین انواع خاصی مورد نیاز است. برای مثال، ویژگی android:background
یک view انتظار یک Drawable
دارد، اما مقدار color
مشخص شده یک عدد صحیح است. مثال زیر یک ویژگی را نشان می دهد که انتظار یک Drawable
دارد، اما به جای آن یک عدد صحیح ارائه شده است:
<View
android:background="@{isError ? @color/red : @color/white}"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
هر زمان که یک Drawable
انتظار می رود و یک عدد صحیح برمی گردد، int
را به یک ColorDrawable
تبدیل کنید. برای انجام تبدیل، از یک روش استاتیک با حاشیه نویسی BindingConversion
به شرح زیر استفاده کنید:
کاتلین
@BindingConversion fun convertColorToDrawable(color: Int) = ColorDrawable(color)
جاوا
@BindingConversion public static ColorDrawable convertColorToDrawable(int color) { return new ColorDrawable(color); }
با این حال، انواع مقادیر ارائه شده در عبارت binding باید سازگار باشند. همانطور که در مثال زیر نشان داده شده است، نمی توانید از انواع مختلف در یک عبارت استفاده کنید:
// 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"/>
برای کسب اطلاعات بیشتر در مورد اتصال داده ها، به منابع زیر مراجعه کنید. محتوا و نمونه کدها در این صفحه مشمول پروانههای توصیفشده در پروانه محتوا هستند. جاوا و OpenJDK علامتهای تجاری یا علامتهای تجاری ثبتشده Oracle و/یا وابستههای آن هستند. تاریخ آخرین بهروزرسانی 2024-08-20 بهوقت ساعت هماهنگ جهانی. منابع اضافی
نمونه ها
Codelabs
پست های وبلاگ
{% کلمه به کلمه %} برای شما توصیه می شود
{% کلمه به کلمه %}