Liên kết khung hiển thị Một phần của Android Jetpack.

Liên kết khung hiển thị là một tính năng giúp bạn dễ dàng viết mã tương tác với khung hiển thị hơn. Sau khi bật tính năng liên kết khung hiển thị trong một mô-đun, mô-đun đó sẽ tạo một lớp liên kết cho từng tệp bố cục XML có trong mô-đun đó. Một thực thể của lớp liên kết có chứa thông tin tham chiếu trực tiếp đến tất cả các chế độ xem có mã nhận dạng trong bố cục tương ứng.

Trong hầu hết các trường hợp, tính năng liên kết thành phần hiển thị sẽ thay thế findViewById.

Thiết lập

Tính năng liên kết khung hiển thị được bật theo từng mô-đun. Để bật tính năng liên kết khung hiển thị trong một mô-đun, hãy đặt tuỳ chọn bản dựng viewBinding thành true trong tệp build.gradle cấp mô-đun, như minh hoạ trong ví dụ sau:

Groovy

android {
    ...
    buildFeatures {
        viewBinding true
    }
}

Kotlin

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

Nếu bạn muốn bỏ qua một tệp bố cục trong khi tạo các lớp liên kết, hãy thêm thuộc tính tools:viewBindingIgnore="true" vào khung hiển thị gốc của tệp bố cục đó:

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

Cách sử dụng

Nếu tính năng liên kết thành phần hiển thị được bật cho một mô-đun, hệ thống sẽ tạo một lớp liên kết cho từng tệp bố cục XML có trong mô-đun đó. Mỗi lớp liên kết chứa thông tin tham chiếu đến khung hiển thị gốc và mọi khung hiển thị có mã nhận dạng. Tên của lớp liên kết được tạo bằng cách chuyển đổi tên của tệp XML theo quy ước viết hoa Pascal case và thêm từ "Binding" vào cuối.

Ví dụ: hãy xem xét tệp bố cục có tên là result_profile.xml có chứa nội dung sau:

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

Lớp liên kết được tạo có tên là ResultProfileBinding. Lớp này có hai trường: một TextView tên là name và một Button tên là button. ImageView trong bố cục không có mã nhận dạng nên không có tham chiếu đến mã này trong lớp liên kết.

Mỗi lớp liên kết cũng bao gồm một phương thức getRoot(), cung cấp thông tin tham chiếu trực tiếp đến khung hiển thị gốc của tệp bố cục tương ứng. Trong ví dụ này, phương thức getRoot() trong lớp ResultProfileBinding sẽ trả về khung hiển thị gốc LinearLayout.

Các phần sau đây minh hoạ cách sử dụng các lớp liên kết được tạo trong hoạt động và mảnh.

Sử dụng tính năng liên kết thành phần hiển thị trong các hoạt động

Để thiết lập một thực thể của lớp liên kết để sử dụng với một hoạt động, hãy thực hiện các bước sau trong phương thức onCreate() của hoạt động:

  1. Gọi phương thức inflate() tĩnh có trong lớp liên kết đã tạo. Thao tác này sẽ tạo một thực thể của lớp liên kết để hoạt động sử dụng.
  2. Lấy thông tin tham chiếu đến khung hiển thị gốc bằng cách gọi phương thức getRoot() hoặc sử dụng cú pháp thuộc tính Kotlin.
  3. Truyền khung hiển thị gốc vào setContentView() để đặt khung hiển thị đó làm khung hiển thị đang hoạt động trên màn hình.

Các bước này được thể hiện trong ví dụ sau đây:

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

Giờ đây, bạn có thể sử dụng thực thể của lớp liên kết để tham chiếu bất kỳ khung hiển thị nào:

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

Sử dụng tính năng liên kết thành phần hiển thị trong mảnh

Để thiết lập một phiên bản của lớp liên kết sử dụng với một mảnh, hãy thực hiện các bước sau trong phương thức onCreateView() của mảnh:

  1. Gọi phương thức inflate() tĩnh có trong lớp liên kết đã tạo. Thao tác này sẽ tạo một phiên bản của lớp liên kết để mảnh sử dụng.
  2. Lấy thông tin tham chiếu đến khung hiển thị gốc bằng cách gọi phương thức getRoot() hoặc sử dụng cú pháp thuộc tính Kotlin.
  3. Trả về khung hiển thị gốc từ phương thức onCreateView() để đặt khung hiển thị đó làm khung hiển thị đang hoạt động trên màn hình.

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

Giờ đây, bạn có thể sử dụng thực thể của lớp liên kết để tham chiếu bất kỳ khung hiển thị nào:

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

Đưa ra gợi ý cho các cấu hình khác nhau

Khi khai báo các khung hiển thị trên nhiều cấu hình, đôi khi, bạn nên sử dụng một loại khung hiển thị khác tuỳ thuộc vào bố cục cụ thể. Đoạn mã sau đây cho thấy một ví dụ:

# in res/layout/example.xml

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

# in res/layout-land/example.xml

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

Trong trường hợp này, bạn có thể muốn lớp được tạo hiển thị trường userBio thuộc loại TextView, vì TextView là lớp cơ sở phổ biến. Do các hạn chế về kỹ thuật, trình tạo mã liên kết khung hiển thị không thể xác định điều này mà thay vào đó tạo ra trường View. Để thực hiện thao tác này, bạn phải truyền trường này vào lúc khác bằng binding.userBio as TextView.

Để khắc phục hạn chế này, tính năng liên kết khung hiển thị hỗ trợ thuộc tính tools:viewBindingType, cho phép bạn cho trình biên dịch biết cần sử dụng loại nào trong mã được tạo. Trong ví dụ trước, bạn có thể sử dụng thuộc tính này để làm cho trình biên dịch tạo trường dưới dạng 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" />

Trong một ví dụ khác, giả sử bạn có 2 bố cục, một bố cục chứa BottomNavigationView và một bố cục khác chứa NavigationRailView. Cả hai lớp đều mở rộng NavigationBarView, trong đó chứa hầu hết thông tin triển khai. Nếu mã của bạn không cần biết chính xác lớp con nào có trong bố cục hiện tại, bạn có thể sử dụng tools:viewBindingType để đặt loại đã tạo thành NavigationBarView trong cả hai bố cục:

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

Liên kết chế độ xem không thể xác thực giá trị của thuộc tính này khi tạo mã. Để tránh lỗi thời gian biên dịch và lỗi thời gian chạy, giá trị phải đáp ứng các điều kiện sau:

  • Giá trị phải là một lớp kế thừa từ android.view.View.
  • Giá trị phải là lớp cấp cao của thẻ được đặt. Ví dụ: các giá trị sau đây không có hiệu lực:

      <TextView tools:viewBindingType="ImageView" /> <!-- ImageView is not related to TextView. -->
      <TextView tools:viewBindingType="Button" /> <!-- Button is not a superclass of TextView. -->
    
  • Loại cuối cùng phải phân giải một cách nhất quán trên tất cả các cấu hình.

Điểm khác biệt với findViewById

Tính năng liên kết chế độ xem có những ưu điểm quan trọng so với việc sử dụng findViewById:

  • Xử lý an toàn giá trị rỗng: vì liên kết khung hiển thị tạo ra các tham chiếu trực tiếp đến các khung hiển thị, nên sẽ không có nguy cơ xảy ra ngoại lệ về con trỏ rỗng do mã khung hiển thị không hợp lệ. Ngoài ra, khi một khung hiển thị chỉ xuất hiện trong một số cấu hình của bố cục, trường chứa tham chiếu của khung hiển thị đó trong lớp liên kết sẽ được đánh dấu bằng @Nullable.
  • An toàn về kiểu: các trường trong mỗi lớp liên kết có kiểu khớp với thành phần hiển thị mà các trường đó tham chiếu trong tệp XML. Điều này có nghĩa là không có nguy cơ xảy ra ngoại lệ truyền lớp.

Những khác biệt này đồng nghĩa với việc bố cục và mã của bạn không tương thích dẫn đến việc bản dựng không hoạt động được tại thời điểm biên dịch thay vì tại thời gian chạy.

So sánh với liên kết dữ liệu

Liên kết khung hiển thị và liên kết dữ liệu đều tạo các lớp liên kết mà bạn có thể dùng để tham chiếu trực tiếp các khung hiển thị. Tuy nhiên, tính năng liên kết khung hiển thị được thiết kế để xử lý các trường hợp sử dụng đơn giản hơn và mang lại những lợi ích sau so với liên kết dữ liệu:

  • Biên dịch nhanh hơn: tính năng liên kết khung hiển thị không cần xử lý chú giải nên thời gian biên dịch sẽ nhanh hơn.
  • Dễ sử dụng: tính năng liên kết khung hiển thị không yêu cầu tệp bố cục XML được gắn thẻ chuyên biệt, nhờ đó, bạn sẽ có thể sử dụng nhanh chóng hơn trong ứng dụng. Sau khi bạn bật tính năng liên kết khung hiển thị trong một mô-đun, thao tác này sẽ tự động áp dụng cho tất cả bố cục của mô-đun đó.

Mặt khác, tính năng liên kết khung hiển thị có các hạn chế sau đây so với liên kết dữ liệu:

Do những điểm cần cân nhắc này, trong một số trường hợp, bạn nên sử dụng cả tính năng liên kết khung hiển thị và liên kết dữ liệu trong một dự án. Bạn có thể dùng tính năng liên kết dữ liệu trong những bố cục yêu cầu các tính năng nâng cao và dùng tính năng liên kết thành phần hiển thị trong những bố cục không yêu cầu như vậy.

Tài nguyên khác

Để tìm hiểu thêm về tính năng liên kết thành phần hiển thị, hãy xem các tài nguyên bổ sung sau đây:

Mẫu

Blog

Video