+5

Understanding LayoutInflater Android

Định nghĩa

LayoutInflate là một component căn bản trên Android. LayoutInflate làm công việc chuyển mã từ một file layout xml lên view.

Có nhiều cách để gọi ra một thể hiện của LayoutInflate

  • Gọi trực tiếp từ context
 LayoutInflater layoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE)

Đây là cách chính thống nhất, tuy nhiên hơi dài dòng chút.

  • Gọi method static từ lớp LayoutInflate
 LayoutInflater layoutInflater = LayoutInflater.from(context)

Cách này gọi này đơn giản, ngắn gọn.

LayoutInflater tiêu tốn thời gian vào các việc:

  • Đọc một xml view
  • Tạo java object
  • Set các thuộc tính (attributes) cho view
  • Làm tương tự cho đến lớp con cuối cùng của view được inflate

Sau khi có một đối tượng LayoutInflate, View được tạo ra như sau

*1
View v = inflater.inflate(R.layout.layout_id, parrent_view)

hoặc

View v = inflater.inflate(R.layout.layout_id, parrent_view, is_attacth)

Android-Home-600x351.jpg

Sai lầm phổ biến với LayoutInflate

Có vẻ sử dụng LayoutInflater khá đơn giản, tuy nhiên lại có nhiều lỗi phổ thông mà có thể bạn đang gặp phải trong ứng dụng của mình. Nếu bạn implement một view bằng đoạn mã sau

1*
inflater.inflater(R.layout.my_layout, null)

thì bạn đang chưa hiểu về LayoutInflater rồi, theo phân tích của Dave Smith, thì dòng mã trên là sai lầm. Hãy nhìn cách LayoutInflater làm việc, có 2 method được cung cấp từ Factory

2*
inflate(int resource, ViewGroup root)
3*
inflate(int resource, ViewGroup root, boolean attachToRoot)

Tham số đầu tiên resource trỏ đến layout muốn inflate vào view, Tham số thứ 2 là gốc của cả cây layout mà bạn muốn add view này vào. Khi attachToRoot được bật, view sẽ được gắn vào cây sau khi thực hiện inflate.

Hai tham số cuối dễ dẫn đến việc viết ra mã lỗi. Hệ thống sẽ tự động thêm view vào trong cây layout như một nốt cuối tuy nhiên trước tiên, nó sẽ phải kiểm tra root: xem có khác null không, được attach chưa, kiểu layout là gì...

Nếu bạn viết như dòng lệnh 1*, nghĩa là cho phép view được tự động thêm vào trực tiếp mà bỏ qua bước quan trọng trên.

  • Nếu view root null, ứng dụng bị crash.
  • Nếu view root chưa được attach, view con cũng sẽ không được attach vào root
  • Thuộc tính của cha không được quan tâm dẫn đến toàn bộ thuộc tính của root trong item con bị bỏ qua, layout bị dựng sai với mong muốn.

Lấy một tình huống ví dụ sau: Adapter là trường hợp hay dùng LayoutInflater để lấy ra đối tượng view con.

getView(int position, View convertView, ViewGroup parent)

Trong khi đó, quá trình vẽ view của fragment thực hiện như sau:

onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)

Bạn có chú ý đến thời gian mà hệ thống muốn inflate một layout? Lưu ý rằng trong phần lớn trường hợp kể cả 2 trường hợp trên nó sẽ throw ra một Exception gọi là LayoutInflatorException.

View cha là một phần quan trọng trong việc tạo thêm môt view con nữa vào root. Quan trọng giống như việc bạn xây nhà mà cần quan tâm móng đầu tiên. Hãy lưu ý khi gặp những câu lệnh tương tự như trường hợp của câu lệnh 1*

Nâng cao: Custom factory LayoutInflaters

LayoutInflater được trình bày ở trên là của hệ thống. Custom Factory LayoutInflaters cho phép linh hoạt cách inflate một xml với tag tuỳ biến, rút bớt xml hoặc thêm tag trong file layout, inflate một view với custom constructor...

Trong ứng dụng hỗ trợ AppCompat, cách quản lý implement view trở nên rất đơn giản.  Đó là nhờ custom factories. LayoutInflater cung cấp 2 method cho phép inflater layout setFactory(LayoutInflater.Factory factory)setFactory2(LayoutInflater.Factory2 factory). Method thứ 2 được update từ phiên bản API 11, do đó nếu target của application là 11+, nên sử dụng Factory2 thay vì Factory.

Class Factory

View oncreateView(String name, Context context, AttributeSet attrs)

Class Factory2

View oncreateView(View parentView, String name, Context context, AttributeSet attrs)

Sử dụng Factory như sau

@Override public void onCreate(Bundle savedInstanceState) {
    LayoutInflaterCompat.setFactory(getLayoutInflater(), new MyLayoutInflaterFactory(this));
    super.onCreate(savedInstanceState);
    ...
}

Lưu ý chỉ có thể set một thể hiện factory ở LayoutInflater. Mỗi LayoutInflater đều có một Factory mặc định của nó.

Happy coding!

REFERENCE http://blog.bradcampbell.nz/layoutinflater-factories/

https://possiblemobile.com/author/daves/

https://dzone.com/articles/android-devs-youre-doing


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí