View binding   جزء من Android Jetpack.

ربط العناصر هي ميزة تسهّل كتابة رمز برمجي يتفاعل مع العناصر. بعد تفعيل ربط العرض في إحدى الوحدات، يتم إنشاء class binding لكل ملف تنسيق XML متوفّر في تلك الوحدة. يحتوي مثيل لفئة الربط على مراجع مباشرة إلى جميع طرق العرض التي لها معرّف في التنسيق المناظر.

في معظم الحالات، يحلّ ربط العرض محلّ findViewById.

ضبط إعدادات الجهاز

يتم تفعيل ربط العرض على أساس كل وحدة على حدة. لتفعيل ربط العناصر في وحدة، اضبط خيار الإنشاء viewBinding على true في ملف build.gradle على مستوى الوحدة، كما هو موضّح في المثال التالي:

رائع

android {
    ...
    buildFeatures {
        viewBinding true
    }
}

Kotlin

android {
    ...
    buildFeatures {
        viewBinding = true
    }
}

إذا أردت تجاهل ملف تنسيق أثناء إنشاء فئات الربط، أضِف سمة tools:viewBindingIgnore="true" إلى العرض الجذر لملف التنسيق:

<LinearLayout
        ...
        tools:viewBindingIgnore="true" >
    ...
</LinearLayout>

الاستخدام

في حال تفعيل ربط العرض لوحدة، يتم إنشاء فئة ربط لكل ملف تنسيق XML يحتوي عليه النموذج. تحتوي كل فئة ربط على إحالات إلى العرض الجذر وجميع العروض التي لها رقم تعريف. يتم إنشاء اسم فئة الربط من خلال تحويل اسم ملف XML إلى تنسيق Pascal case وإضافة الكلمة "Binding" في النهاية.

على سبيل المثال، ملف تنسيق يُسمى result_profile.xml يحتوي على ما يلي:

<LinearLayout ... >
    <TextView android:id="@+id/name" />
    <ImageView android:cropToPadding="true" />
    <Button android:id="@+id/button"
        android:background="@drawable/rounded_button" />
</LinearLayout>

تُسمى فئة الربط التي تم إنشاؤها ResultProfileBinding. تحتوي هذه الفئة على حقلين: TextView باسم name وButton باسم button. لا يحتوي العنصر ImageView في التنسيق على معرّف، لذا لا تتم الإشارة إليه في فئة الربط.

تتضمّن كل فئة ربط أيضًا طريقة getRoot()، ما يقدّم مرجعًا مباشرًا للعرض الجذر لملف التنسيق المقابل. في هذا المثال، تعرض المحاولة getRoot() في فئةResultProfileBinding المحاولة LinearLayout العرض الجذر.

توضِّح الأقسام التالية استخدام فئات الربط التي تم إنشاؤها في الأنشطة والشرائح.

استخدام ربط العرض في الأنشطة

لإعداد مثيل لفئة الربط لاستخدامه مع نشاط، نفِّذ الخطوات التالية في onCreate() النشاط:

  1. استدعاء طريقة inflate() الثابتة المضمّنة في فئة الربط التي تم إنشاؤها يؤدي ذلك إلى إنشاء مثيل لفئة الربط لاستخدامه في النشاط.
  2. يمكنك الحصول على مرجع إلى طريقة العرض الجذر من خلال استدعاء طريقة getRoot() أو باستخدام بنية Kotlin.
  3. نقْل العرض الجذر إلى setContentView() لجعله العرض النشط على الشاشة.

يتم عرض هذه الخطوات في المثال التالي:

Kotlin

private lateinit var binding: ResultProfileBinding

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    binding = ResultProfileBinding.inflate(layoutInflater)
    val view = binding.root
    setContentView(view)
}

Java

private ResultProfileBinding binding;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    binding = ResultProfileBinding.inflate(getLayoutInflater());
    View view = binding.getRoot();
    setContentView(view);
}

يمكنك الآن استخدام مثيل فئة الربط للإشارة إلى أيّ من طرق العرض:

Kotlin

binding.name.text = viewModel.name
binding.button.setOnClickListener { viewModel.userClicked() }

Java

binding.name.setText(viewModel.getName());
binding.button.setOnClickListener(new View.OnClickListener() {
    viewModel.userClicked()
});

استخدام ربط العرض في الأجزاء

لإعداد مثيل لفئة الربط لاستخدامه مع جزء، نفِّذ الخطوات التالية في onCreateView() طريقة الجزء:

  1. استدعاء الطريقة الثابتة inflate() المضمّنة في فئة الربط التي تم إنشاؤها يؤدي ذلك إلى إنشاء مثيل لفئة الربط لاستخدامه في المقتطف.
  2. يمكنك الحصول على مرجع إلى طريقة العرض الجذر من خلال استدعاء طريقة getRoot() أو باستخدام بنية Kotlin.
  3. ارجع العرض الجذر من الطريقة onCreateView() لجعله العرض النشط على الشاشة.

Kotlin

private var _binding: ResultProfileBinding? = null
// This property is only valid between onCreateView and
// onDestroyView.
private val binding get() = _binding!!

override fun onCreateView(
    inflater: LayoutInflater,
    container: ViewGroup?,
    savedInstanceState: Bundle?
): View? {
    _binding = ResultProfileBinding.inflate(inflater, container, false)
    val view = binding.root
    return view
}

override fun onDestroyView() {
    super.onDestroyView()
    _binding = null
}

Java

private ResultProfileBinding binding;

@Override
public View onCreateView (LayoutInflater inflater,
                          ViewGroup container,
                          Bundle savedInstanceState) {
    binding = ResultProfileBinding.inflate(inflater, container, false);
    View view = binding.getRoot();
    return view;
}

@Override
public void onDestroyView() {
    super.onDestroyView();
    binding = null;
}

يمكنك الآن استخدام مثيل فئة الربط للإشارة إلى أيّ من طرق العرض:

Kotlin

binding.name.text = viewModel.name
binding.button.setOnClickListener { viewModel.userClicked() }

Java

binding.name.setText(viewModel.getName());
binding.button.setOnClickListener(new View.OnClickListener() {
    viewModel.userClicked()
});
.

تقديم نصائح حول الإعدادات المختلفة

عند تحديد طرق العرض في عمليات ضبط متعدّدة، قد يكون من المفيد في بعض الأحيان استخدام نوع عرض مختلف استنادًا إلى التنسيق المحدّد. يوضّح مقتطف الرمز التالي مثالاً على ذلك:

# in res/layout/example.xml

<TextView android:id="@+id/user_bio" />

# in res/layout-land/example.xml

<EditText android:id="@+id/user_bio" />

في هذه الحالة، قد تتوقّع أن تعرض الفئة التي تم إنشاؤها حقل userBio من النوع TextView، لأنّ TextView هي الفئة الأساسية الشائعة. بسبب قيود فنية، لا يمكن لأداة إنشاء رموز ربط العروض تحديد ذلك، ولذلك تنشئ حقل View بدلاً من ذلك. يتطلّب ذلك تحويل الحقل لاحقًا باستخدام binding.userBio as TextView.

للتغلب على هذا القيد، يتيح ربط العرض استخدام سمة tools:viewBindingType ، ما يتيح لك إخبار المُجمِّع بالنوع الذي يجب استخدامه في الرمز الذي تم إنشاؤه. في المثال السابق، يمكنك استخدام هذه السمة لجعل المُجمِّع ينشئ الحقل على أنّه TextView:

# in res/layout/example.xml (unchanged)

<TextView android:id="@+id/user_bio" />

# in res/layout-land/example.xml

<EditText android:id="@+id/user_bio" tools:viewBindingType="TextView" />

في مثال آخر، لنفترض أنّ لديك تنسيقَين، أحدهما يحتوي على BottomNavigationView والآخر يحتوي على NavigationRailView. تمتد كلتا کلاستَي NavigationBarView، اللتين تحتويان على معظم تفاصيل التنفيذ. إذا لم يكن رمزك البرمجي بحاجة إلى معرفة الفئة الفرعية المحدّدة المتوفّرة في التنسيق الحالي، يمكنك استخدام tools:viewBindingType لضبط نوع العنصر الذي تم إنشاؤه على NavigationBarView في كلا التنسيقَين:

# in res/layout/navigation_example.xml

<BottomNavigationView android:id="@+id/navigation" tools:viewBindingType="NavigationBarView" />

# in res/layout-w720/navigation_example.xml

<NavigationRailView android:id="@+id/navigation" tools:viewBindingType="NavigationBarView" />

لا يمكن لربط العرض التحقّق من قيمة هذه السمة عند إنشاء الرمز. لتجنُّب أخطاء وقت الترجمة ووقت التشغيل، يجب أن تستوفي القيمة الشروط التالية:

  • يجب أن تكون القيمة فئة ترث من android.view.View.
  • يجب أن تكون القيمة فئة فائقة للعلامة التي يتم وضعها عليها. على سبيل المثال، لا تعمل القيم التالية:

      <TextView tools:viewBindingType="ImageView" /> <!-- ImageView is not related to TextView. -->
      <TextView tools:viewBindingType="Button" /> <!-- Button is not a superclass of TextView. -->
    
  • يجب أن يتم حلّ النوع النهائي بشكلٍ متسق في جميع الإعدادات.

الاختلافات عن findViewById

يقدّم ربط العرض مزايا مهمة مقارنةً باستخدام findViewById:

  • أمان القيم الخالية: بما أنّ ربط العناصر ينشئ إحالات مباشرة إلى العناصر، لا يُحتمل حدوث استثناء مؤشر فارغ بسبب معرّف عنصر غير صالح. بالإضافة إلى ذلك، عندما لا يظهر عرض إلا في بعض إعدادات ملف تخطيط، يتم وضع علامة @Nullable على الحقل الذي يحتوي على مرجعه في فئة الربط.
  • أمان النوع: تحتوي الحقول في كل فئة ربط على أنواع تتطابق مع العروض التي تشير إليها في ملف XML. وهذا يعني أنّه ما مِن خطر بحدوث استثناء عند محاولة تحويل مثيل فئة.

تعني هذه الاختلافات أنّ حالات عدم التوافق بين التنسيق والرمز المبرمَج تؤدي إلى تعذُّر إنشاء التطبيق في وقت الترجمة بدلاً من وقت التشغيل.

المقارنة مع ربط البيانات

يُنشئ كلّ من ربط العناصر المرئية وربط البيانات فئات ربط يمكنك استخدامها للإشارة إلى العناصر المرئية مباشرةً. ومع ذلك، يهدف ربط الاطِّلاع إلى التعامل مع حالات استخدام أبسط ويقدّم الفوائد التالية مقارنةً بربط البيانات:

  • الترجمة أسرع: لا يتطلّب ربط العناصر معالجة التعليقات التوضيحية، لذا تكون أوقات الترجمة أسرع.
  • سهولة الاستخدام: لا يتطلّب ربط العناصر بالعرض استخدام ملفات تنسيق XML مُشارَك إليها بشكل خاص، لذا يمكن اعتماده في تطبيقاتك بشكل أسرع. بعد تفعيل ربط العرض في وحدة، يتم تطبيقه على جميع تنسيقات هذه الوحدة تلقائيًا.

من ناحية أخرى، فإنّ ربط العرض له القيود التالية مقارنةً بربط data:

وبناءً على هذه الاعتبارات، من الأفضل في بعض الحالات استخدام كلّ من ربط الاطِّلاع وربط البيانات في المشروع. يمكنك استخدام ربط البيانات في التنسيقات التي تتطلب ميزات متقدّمة واستخدام ربط العرض في التنسيقات التي لا تتطلّب ذلك.

مصادر إضافية

لمزيد من المعلومات عن ربط العناصر، اطّلِع على المراجع الإضافية التالية:

المدوّنات

الفيديوهات