مشاهده بخش صحافی Android Jetpack .

View binding یک ویژگی است که نوشتن کدی را که با نماها در تعامل است را آسان‌تر می‌کند. هنگامی که view binding در یک ماژول فعال می شود، یک کلاس binding برای هر فایل طرح بندی XML موجود در آن ماژول ایجاد می کند. یک نمونه از یک کلاس binding شامل ارجاع مستقیم به تمام نماهایی است که دارای شناسه در طرح مربوطه هستند.

در بیشتر موارد، view binding جایگزین findViewById می شود.

راه اندازی

View binding به صورت ماژول به ماژول فعال است. برای فعال کردن view binding در یک ماژول، همانطور که در مثال زیر نشان داده شده است، گزینه viewBinding build را در فایل build.gradle سطح ماژول روی true تنظیم کنید:

شیار

android {
    ...
    buildFeatures {
        viewBinding true
    }
}

کاتلین

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

اگر می‌خواهید هنگام تولید کلاس‌های binding، یک فایل layout نادیده گرفته شود، ویژگی tools:viewBindingIgnore="true" به نمای ریشه آن فایل طرح‌بندی اضافه کنید:

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

استفاده

اگر view binding برای یک ماژول فعال باشد، یک کلاس binding برای هر فایل طرح بندی XML که ماژول حاوی آن است ایجاد می شود. هر کلاس binding شامل ارجاعاتی به نمای ریشه و ��مام نماهایی است که دارای شناسه هستند. نام کلاس binding با تبدیل نام فایل XML به حروف پاسکال و افزودن کلمه Binding به انتهای آن ایجاد می شود.

به عنوان مثال، یک فایل layout به نام 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 در layout هیچ شناسه ای ندارد، بنابراین هیچ مرجعی به آن در کلاس binding وجود ندارد.

هر کلاس binding همچنین شامل یک متد getRoot() است که یک مرجع مستقیم برای نمای ریشه فایل layout مربوطه ارائه می دهد. در این مثال، متد getRoot() در کلاس ResultProfileBinding نمای ریشه LinearLayout را برمی گرداند.

بخش های زیر استفاده از کلاس های اتصال تولید شده در فعالیت ها و قطعات را نشان می دهد.

از view binding در فعالیت ها استفاده کنید

برای تنظیم یک نمونه از کلاس binding برای استفاده با یک اکتیویتی، مراحل زیر را در متد onCreate() اکتیویتی انجام دهید:

  1. متد static inflate() موجود در کلاس binding تولید شده را فراخوانی کنید. این یک نمونه از کلاس binding برای فعالیت ایجاد می کند.
  2. با فراخوانی متد getRoot() یا با استفاده از نحو ویژگی Kotlin، به نمای ریشه ارجاع دهید.
  3. نمای root را به setContentView() منتقل کنید تا به نمای فعال روی صفحه تبدیل شود.

این مراحل در مثال زیر نشان داده شده است:

کاتلین

private lateinit var binding: ResultProfileBinding

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

جاوا

private ResultProfileBinding binding;

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

اکنون می توانید از نمونه کلاس binding برای ارجاع به هر یک از view ها استفاده کنید:

کاتلین

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

جاوا

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

از view binding در قطعات استفاده کنید

برای تنظیم نمونه ای از کلاس binding برای استفاده با یک قطعه، مراحل زیر را در متد onCreateView() قطعه انجام دهید:

  1. متد static inflate() موجود در کلاس binding تولید شده را فراخوانی کنید. این یک نمونه از کلاس binding را برای استفاده از قطعه ایجاد می کند.
  2. با فراخوانی متد getRoot() یا با استفاده از نحو ویژگی Kotlin، به نمای ریشه ارجاع دهید.
  3. نمای ریشه را از متد onCreateView() برگردانید تا به نمای فعال روی صفحه تبدیل شود.

کاتلین

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
}

جاوا

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;
}

اکنون می توانید از نمونه کلاس binding برای ارجاع به هر یک از view ها استفاده کنید:

کاتلین

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

جاوا

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 نمی‌تواند این را تعیین کند و به جای آن یک فیلد View ایجاد می‌کند. این مستلزم فرستادن فیلد بعداً با binding.userBio as TextView .

برای رفع این محدودیت، view binding از ویژگی 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" />

View binding نمی تواند ارزش این ویژگی را هنگام تولید کد تأیید کند. برای جلوگیری از خطاهای زمان کامپایل و زمان اجرا، مقدار باید دارای شرایط زیر باشد:

  • مقدار باید کلاسی باشد که از 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

View binding مزایای مهمی نسبت به استفاده از findViewById دارد:

  • ایمنی تهی: از آنجایی که binding view ارجاع مستقیم به نماها ایجاد می کند، به دلیل شناسه نمای نامعتبر، خطر استثنای اشاره گر تهی وجود ندارد. علاوه بر این، زمانی که یک view فقط در برخی از تنظیمات یک طرح‌بندی وجود دارد، فیلد حاوی مرجع آن در کلاس binding با @Nullable علامت‌گذاری می‌شود.
  • نوع ایمنی: فیلدهای هر کلاس binding دارای انواعی هستند که با نماهایی که در فایل XML به آنها ارجاع می دهند مطابقت دارند. این بدان معنی است که هیچ خطری برای استثناء بازیگران کلاس وجود ندارد.

این تفاوت ها به معنای ناسازگاری بین طرح و کد شما است که منجر به شکست ساخت شما در زمان کامپایل و نه در زمان اجرا می شود.

مقایسه با اتصال داده ها

View binding و data binding هر دو کلاس های binding را ایجاد می کنند که می توانید از آنها برای ارجاع مستقیم به نماها استفاده کنید. با این حال، view binding برای رسیدگی به موارد استفاده ساده‌تر در نظر گرفته شده است و مزایای زیر را نسبت به داده‌ها ارائه می‌کند:

  • کامپایل سریعتر: اتصال مشاهده نیازی به پردازش حاشیه نویسی ندارد، بنابراین زمان کامپایل سریعتر است.
  • سهولت استفاده: مشاهده صحافی به فایل‌های طرح‌بندی XML با برچسب‌گذاری خاص نیاز ندارد، بنابراین در برنامه‌های شما سریع‌تر اجرا می‌شود. هنگامی که View binding را در یک ماژول فعال می‌کنید، به طور خودکار برای همه طرح‌بندی‌های آن ماژول اعمال می‌شود.

از طرف دیگر، view binding در مقایسه با data binding دارای محدودیت‌های زیر است:

به دلیل این ملاحظات، در برخی موارد بهتر است از هر دو view binding و data binding در پروژه استفاده شود. می‌توانید در طرح‌بندی‌هایی که نیاز به ویژگی‌های پیشرفته دارند، از اتصال داده‌ها استفاده کنید و در طرح‌بندی‌هایی که نیازی به ویژگی‌های پیشرفته ندارند، از پیوند مشاهده استفاده کنید.

منابع اضافی

برای کسب اطلاعات بیشتر در مورد مشاهده binding، به منابع اضافی زیر مراجعه کنید:

نمونه ها

وبلاگ ها

ویدیوها

{% کلمه به کلمه %} {% آخر کلمه %} {% کلمه به کلمه %} {% آخر کلمه %}