ViewStub - cao hơn, thông minh hơn!

Bài viết trước đã giới thiệu cho các bạn cách sử dụng lại layout vô cùng dễ dàng với tag<include />. Tuy nhiên bạn cần thận trọng vì đôi khi sử dụng một view dư thừa lặp đi lặp lại sẽ làm giảm tốc độ xử lý màn hình. Khi gặp vấn đề này, ViewStub là một lựa chọn hoàn hảo.

ViewStub có kích thước bằng 0 và không yêu cầu Android "vẽ" bất cứ gì lên màn hình. Vì vậy inflate một ViewStub rất nhanh và không tốn bộ nhớ. Có thể coi ViewStub là một tag "đặt gạch": Layout mẹ đã biết nó ở đâu rồi, nhưng khi nào gọi thì nó mới hiện lên!

Trường hợp nên sử dụng ViewStub

Hình ảnh dưới đây mô tả một layout thư viện sách gồm nhiều cuốn sách và thông tin về chúng:

Khi thực hiện tiến trình tải thêm sách mới vào, một thanh công cụ hiển thị tốc độ gồm 1 ProgressBar và 1 Button sẽ hiện lên:

Vì tiến trình này sẽ không cần phải thực hiện thường xuyên, ta có thể bỏ nó vào ViewStub. Và khi cần, ta gọi ViewStub này để nó inflate layout thanh công cụ như trên. Khi hoàn thành tiến trình, ta "giấu" layout đi vào lại ViewStub.

Điểm khác biệt của ViewStub so với tag <include />

  • Tag <include /> có tác dụng dán toàn bộ code trong file xml vào layout mẹ, như một file thống nhất. Vì thế khi inflate layout mẹ thì toàn bộ layout trong tag <include /> cũng sẽ được inflate.
  • Tag <ViewStub /> tối ưu hơn vì khi inflate layout mẹ sẽ không phải inflate layout con trong ViewStub, và layout con này sẽ chỉ được inflate khi chúng ta cần sử dụng. Việc này giúp giảm khối lượng view phải inflate lúc khởi động.

Cách sử dụng

Cũng như tag <include />, bạn chỉ cần khai báo layout con ở thông số android:layout. Ngoài ra cần khai báo 2 loại id là id của stub (android:id) và id sau khi đã được inflate(android:inflatedId). Các thông số khác của ViewStub sẽ được áp dụng vào root của layout con sau khi inflate. Dưới đây là ví dụ một ViewStub:

<ViewStub
  android:id="@+id/stub_import"
  android:inflatedId="@+id/panel_import"

  android:layout="@layout/progress_overlay"

  android:layout_width="fill_parent"
  android:layout_height="wrap_content"
  android:layout_gravity="bottom" />

Khi cần layout xuất hiện, chỉ cần gọi hàm inflate() cho view đó hoặc set thuộc tính visibility thành VISIBLE (hiện hữu) hoặc INVISIBLE (vô hình nhưng kích thước khác 0). Lưu ý là dùng inflate() thì bạn sẽ có được root của layout. Ví dụ:

((ViewStub) findViewById(R.id.stub_import)).setVisibility(View.VISIBLE);
// hoặc
View importPanel = ((ViewStub) findViewById(R.id.stub_import)).inflate();

Một số lưu ý

  • Hiện tại ViewStub không hỗ trợ tag <merge /> trong nó.
  • Khi 1 stub được gọi inflate() hoặc setVisibility(int), nó sẽ biến mất khỏi layout tổng. Chính vì vậy bạn không cần lưu ánh xạ của ViewStub mà chỉ cần lưu ánh xạ của view có trong nó.

Người viết: MinhNhật.

__________________

Nguồn tham khảo:

  1. https://developer.android.com/training/improving-layouts/loading-ondemand.html
  2. https://android-developers.googleblog.com/2009/03/android-layout-tricks-3-optimize-with.html

results matching ""

    No results matching ""