বাঁধাই অ্যাডাপ্টার

বাইন্ডিং অ্যাডাপ্টার মান সেট করার জন্য উপযুক্ত ফ্রেমওয়ার্ক কল করার জন্য দায়ী। একটি উদাহরণ হল একটি সম্পত্তি মান সেট করা, যেমন setText() পদ্ধতিতে কল করা। আরেকটি উদাহরণ হল একটি ইভেন্ট লিসেনার সেট করা, যেমন setOnClickListener() পদ্ধতিতে কল করা।

ডেটা বাইন্ডিং লাইব্রেরি আপনাকে একটি মান সেট করার জন্য বলা পদ্ধতিটি নির্দিষ্ট করতে দেয়, আপনার নিজস্ব বাঁধাই লজিক প্রদান করে এবং অ্যাডাপ্টার ব্যবহার করে প্রত্যাবর্তিত বস্তুর ধরন নির্দিষ্ট করতে দেয়।

বৈশিষ্ট্য মান সেট করুন

যখনই একটি আবদ্ধ মান পরিবর্তিত হয়, উত্পন্ন বাইন্ডিং ক্লাসটি অবশ্যই বাইন্ডিং এক্সপ্রেশন সহ ভিউতে একটি সেটটার পদ্ধতি কল করবে। আপনি ডেটা বাইন্ডিং লাইব্রেরীকে স্বয়ংক্রিয়ভাবে পদ্ধতি নির্ধারণ করতে দিতে পারেন, অথবা আপনি স্পষ্টভাবে পদ্ধতিটি ঘোষণা করতে পারেন বা একটি পদ্ধতি নির্বাচন করতে কাস্টম যুক্তি প্রদান করতে পারেন।

স্বয়ংক্রিয় পদ্ধতি নির্বাচন

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 টীকা রয়েছে৷ নিম্নলিখিত উদাহরণ 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());
}

পরামিতি প্রকারগুলি গুরুত্বপূর্ণ। প্রথম প্যারামিটারটি বৈশিষ্ট্যের সাথে সম্পর্কিত দৃশ্যের ধরন নির্ধারণ করে। দ্বিতীয় প্যারামিটার প্রদত্ত অ্যাট্রিবিউটের জন্য বাইন্ডিং এক্সপ্রেশনে গৃহীত প্রকার নির্ধারণ করে।

বাইন্ডিং অ্যাডাপ্টারগুলি অন্যান্য ধরণের কাস্টমাইজেশনের জন্যও কার্যকর। উদাহরণস্বরূপ, একটি চিত্র লোড করার জন্য একটি কর্মী থ্রেড থেকে একটি কাস্টম লোডার কল করা যেতে পারে।

আপনার কাছে এমন অ্যাডাপ্টারও থাকতে পারে যেগুলি একাধিক বৈশিষ্ট্য গ্রহণ করে, যেমনটি নিম্নলিখিত উদাহরণে দেখানো হয়েছে:

কোটলিন

@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}" />

অ্যাডাপ্টারটিকে বলা হয় যদি একটি ImageView বস্তুর জন্য imageUrl এবং error ব্যবহার করা হয়, 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 সেট করতে পারেন:

কোটলিন

@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 ক্লাসটি OnAttachStateChangeListener এর জন্য সেটারের পদ্ধতির পরিবর্তে addOnAttachStateChangeListener() এবং removeOnAttachStateChangeListener() পদ্ধতি ব্যবহার করে। android.databinding.adapters.ListenerUtil ক্লাস এই শ্রোতাদের ট্র্যাক রাখতে সাহায্য করে যাতে তাদের বাইন্ডিং অ্যাডাপ্টার থেকে সরানো যায়।

বস্তুর রূপান্তর

স্বয়ংক্রিয় বস্তু রূপান্তর

যখন একটি Object একটি বাইন্ডিং এক্সপ্রেশন থেকে ফেরত দেওয়া হয়, লাইব্রেরি সম্পত্তির মান সেট করতে ব্যবহৃত পদ্ধতি নির্বাচন করে। Object নির্বাচিত পদ্ধতির একটি পরামিতি টাইপের জন্য নিক্ষেপ করা হয়। নিম্নলিখিত উদাহরণে দেখানো হিসাবে, ডেটা সঞ্চয় করতে ObservableMap ক্লাস ব্যবহার করে অ্যাপগুলিতে এই আচরণটি সুবিধাজনক:

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

এক্সপ্রেশনে userMap অবজেক্টটি একটি মান প্রদান করে, যা android:text অ্যাট্রিবিউটের মান সেট করতে ব্যবহৃত setText(CharSequence) পদ্ধতিতে পাওয়া প্যারামিটার টাইপটিতে স্বয়ংক্রিয়ভাবে কাস্ট হয়। যদি প্যারামিটারের ধরনটি অস্পষ্ট হয়, তাহলে এক্সপ্রেশনে রিটার্ন টাইপটি কাস্ট করুন।

কাস্টম রূপান্তর

কিছু পরিস্থিতিতে, নির্দিষ্ট ধরণের মধ্যে একটি কাস্টম রূপান্তর প্রয়োজন। উদাহরণস্বরূপ, একটি ভিউয়ের android:background অ্যাট্রিবিউটটি একটি 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);
}

যাইহোক, বাইন্ডিং এক্সপ্রেশনে প্রদত্ত মান প্রকারগুলি অবশ্যই সামঞ্জস্যপূর্ণ হতে হবে। আপনি একই অভিব্যক্তিতে বিভিন্ন ধরনের ব্যবহার করতে পারবেন না, যেমনটি নিম্নলিখিত উদাহরণে দেখানো হয়েছে:

// 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"/>

অতিরিক্ত সম্পদ

ডেটা বাইন্ডিং সম্পর্কে আরও জানতে, নিম্নলিখিত সংস্থানগুলি দেখুন।

নমুনা

কোডল্যাব

ব্লগ পোস্ট

{% শব্দার্থে %} {% endverbatim %} {% শব্দার্থে %} {% endverbatim %}