View binding חלק מ-Android Jetpack.
קישור תצוגות הוא תכונה שמאפשרת לכתוב בקלות רבה יותר קוד שמקיים אינטראקציה עם תצוגות. אחרי שמפעילים את קישור התצוגה במודול, נוצר שיעור קישור לכל קובץ פריסה של XML שנמצא באותו מודול. מופע של כיתה מקשרת מכיל הפניות ישירות לכל התצוגות שיש להן מזהה בפריסה המתאימה.
ברוב המקרים, קישור התצוגה מחליף את findViewById
.
הגדרה
קישור התצוגה מופעל על בסיס מודול. כדי להפעיל קישור תצוגות במודול, מגדירים את אפשרות ה-build viewBinding
לערך true
בקובץ build.gradle
ברמת המודול, כפי שמתואר בדוגמה הבאה:
Groovy
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()
של הפעילות:
- קוראים ל-method הסטטי
inflate()
שכלול בכיתה הקישור שנוצרה. כך נוצר מופע של סוג הקישור לשימוש בפעילות. - כדי לקבל הפניה לתצוגת הבסיס, אפשר להפעיל את השיטה
getRoot()
או להשתמש בתחביר של נכסי Kotlin. - מעבירים את תצוגת הבסיס אל
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() });
שימוש בקישור תצוגות בקטעי קוד (fragments)
כדי להגדיר מופע של סוג הקישור לשימוש עם קטע, מבצעים את השלבים הבאים ב-method onCreateView()
של הקטע:
- קוראים ל-method הסטטי
inflate()
שכלול בכיתה הקישור שנוצרה. כך נוצרת מופע של כיתה הקישור לשימוש בפלח. - כדי לקבל הפניה לתצוגת הבסיס, אפשר להפעיל את השיטה
getRoot()
או להשתמש בתחביר של נכסי Kotlin. - מחזירים את תצוגת הבסיס מהשיטה
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
:
- בטיחות מפני Null: מאחר שקישור תצוגות יוצר הפניות ישירות לתצוגות, אין סיכון לחריגה מסוג null pointer עקב מזהה תצוגה לא תקין.
בנוסף, כשתצוגה קיימת רק בהגדרות מסוימות של פריסה, השדה שמכיל את ההפניה שלה בכיתה של הקישור מסומן ב-
@Nullable
. - בטיחות סוגים: לשדות בכל כיתה של קישור יש סוגים שתואמים לתצוגות שהן מפנות אליהן בקובץ ה-XML. המשמעות היא שאין סיכון לחריגה של הטמעת סוג (cast).
ההבדלים האלה גורמים לכך שחוסר תאימות בין הפריסה לקוד גורם לכישלון ה-build בזמן הידור ולא בזמן הריצה.
השוואה לקישור נתונים
גם קישור תצוגות וגם קישור נתונים יוצרים כיתות קישור שאפשר להשתמש בהן כדי להפנות לתצוגות ישירות. עם זאת, קישור תצוגות מיועד לטיפול בתרחישי שימוש פשוטים יותר, והוא מספק את היתרונות הבאים בהשוואה לקישור נתונים:
- זמן הידור מהיר יותר: קישור תצוגה לא מחייב עיבוד של הערות, ולכן זמני ההידור מהירים יותר.
- קלות השימוש: כדי להשתמש בקישור תצוגות לא נדרשים קובצי פריסה של XML עם תגים מיוחדים, כך שקל יותר להטמיע אותו באפליקציות. אחרי שמפעילים קישור תצוגה במודול, הוא חל באופן אוטומטי על כל הפריסות של אותו מודול.
לעומת זאת, לקישור תצוגות יש את המגבלות הבאות בהשוואה לקישור נתונים:
- קישור תצוגה לא תומך במשתני פריסה או בביטויים של פריסה, ולכן אי אפשר להשתמש בו כדי להצהיר על תוכן דינמי של ממשק משתמש ישירות מקובצי פריסה של XML.
- קישור תצוגות לא תומך בקישור נתונים דו-כיווני.
בגלל השיקולים האלה, במקרים מסוימים עדיף להשתמש גם בקישור תצוגה וגם בקישור נתונים בפרויקט. אפשר להשתמש בקישור נתונים בפריסות שדורשות תכונות מתקדמות, ולהשתמש בקישור תצוגה בפריסות שלא דורשות תכונות כאלה.
מקורות מידע נוספים
מידע נוסף על קישור תצוגות זמין במקורות המידע הבאים:
בלוגים
סרטונים
מומלץ עבורך
- הערה: טקסט הקישור מוצג כש-JavaScript מושבת
- מעבר מ-Kotlin synthetics ל-Jetpack view binding
- פריסות וביטויי קישור
- ארכיטקטורת אפליקציות: שכבת ממשק המשתמש – תחילת העבודה – מפתחי Android