Sự khác nhau giữa @id/ và @+id/ trong Android


Chào các bạn!

Sau một thời gian vắng bóng do bận thi và có khá nhiều việc trên công ty thì hôm nay mình sẽ trở lại với một bài viết nho nhỏ :D

Khi lập trình Android, đặc biệt là khi xử lý với các XML layout bạn chắc hẳn phải gặp qua thuộc tính "id" trong các thẻ View hoặc Layout. Khi mới học chúng ta có thể hiểu đơn giản là nó sẽ gán hoặc gọi id của các View hoặc Layout đó. Tuy nhiên đôi khi bạn thấy nó có sự xuất hiện của các cách gọi, gán id khác nhau như:
- android:id="@id/myView"
 - android:id="@android:id/myView"
- android:id="@+id/myView"

Vậy chúng khác nhau ra sao, và được dùng trong các trường hợp như thế nào?



Thứ nhất, các bạn nên biết "android:" là tiền tố để chỉ đến các thuộc tính, layout được định sẵn trong android. Không chỉ riêng "@android:id/mà còn nhiều thứ khác như "@android:color/", "@android:drawable/", "@android:layout/"... 
Đây là những tài nguyên PHỔ BIẾNAndroid System đã định sẵn cho nhà lập trình để sử dụng vào các project của họ.

Ví dụ:
Bạn còn nhớ khi tạo một ArrayAdapter cho ListView ta có sử dụng tham số  android.R.layout.simple_list_item_1, hay đơn giản hơn khi dùng "@android:color/transparent" để chỉ màu trong suốt, được rất nhiều người sử dụng, nên android đã tạo ra nó, và tất cả những gì lập trình viên cần là gọi ra và sử dụng. 


Đó là Android Resources, còn khi làm việc với những tài nguyên do chính bạn tạo/defined trong project. Bạn sẽ sử dụng "@id/" và "@+id/"

Căn bản thì bạn có thể không cần suy nghĩ gì cả, hãy sử dụng "@+id/" ở tất cả các chỗ bạn muốn.
Tuy nhiên hiểu sao cho đúng thì là một vấn đề khác. Nếu đơn giản là những gì bạn thích, thì bạn có thể bỏ qua những phần bên dưới!

-----------------------------------------------------------

Khi bạn sử dụng "@+id/myView" thì dấu "+" nói với Android System rằng đây là một tài nguyên mới với tên là "myView" cần được tạo và thêm vào kho tài nguyên (resources) chung. (trong file R.java) NẾU NÓ CHƯA TỒN TẠI. Và sau đó trong Java code bạn sẽ gọi lại các entry đó trong R.java ra bằng cách View view = findViewById(R.id.myView)Quá trình tạo file R.java đó sẽ diễn ra lúc app bạn được compile. 

Mặt khác, khi bạn sử dụng "@id/myView", bạn đang liên kết, refer đến một tài nguyên đã được định nghĩa từ trước bằng "@+id/" và đã tồn tại trong R.java.

File R.java mẫu

Ví dụ:
Trong XML Layout:
- Khi bạn sử dụng thuộc tính "android:id=..." nghĩa là bạn đang muốn xác định id cho một View/Layout mới và cần hướng dẫn cho parser/builder tạo một entry mới trong R.java. Khi đó bạn sẽ phải thêm dấu "+" vào như "android:id=@+id/myView",...
- Khi bạn muốn tham chiếu đến id của một View/Layout khác đã được định nghĩa trước như android:layout_below="@id/myTextView", android:layout_toRightOf="@id/myTextView", ... thì chỉ cần sử dụng "@id/", parser sẽ tự động hiểu và link đến entry đó trong R.java.

Vậy có trường hợp ngoại lệ nào không? 

Xin trả lời là có!

XML Layout của Android có một điểm yếu, nó không như Java code, bạn viết 1 hàm bất kì đâu trong file .java, bạn đều gọi được, không phân biệt thứ tự. Ở đây nó sẽ parse từ trên xuống, nên nếu bạn viết như thế này, thì xuất hiện lỗi lúc compile-time, vì nó không tìm thấy R.id.check.


Rõ ràng đoạn xml trên mình đã dùng "
@+id/check" nghĩa là phải có check trong R.java rồi chứ. Tại sao Android lại bảo không có? :D
...
Bạn đã có câu trả lời cho mình chưa nào? :D

Vậy trong trường hợp này ta sẽ có hai cách giải quyết.

Thứ nhất, đem thẻ Button với id.start xuống dưới Button với id.check.


Như vậy dù thay đổi thứ tự trong xml layout, nhưng thứ tự thực tế khi parse ra vẫn không thay đổi khi sử dụng RelativeLayout. Còn LinearLayout thì sai bét nhé :D
Mặt khác code như thế này làm cho người lập trình viên đọc cảm thấy confused, khó hiểu, dẫn đến dễ gây ra nhầm lẫn, bug không đáng có.

Vậy lỡ gặp LinearLayout hay để dễ đọc hơn thì ta sẽ làm thế nào?
Đơn giản, ta thấy trong đây "check" xuất hiện nhiều hơn 1 lần. Vậy nhớ lại qui tắc. Lần đầu tiên dùng "@+id/" để thêm vào, rồi từ đó có thể refer đến nó bằng "@id/".


Và mọi thứ sẽ chạy tốt như bình thường, người lập trình cũng dễ đọc hơn.

Dường như mọi thứ tưởng chừng như đang dễ hiểu khi làm việc với XML Layout trong Android, mà mình lại làm cho nó trở nên khó hiểu nhỉ :D
Biết nhiều hơn một tí cũng tốt mà. Còn dùng thì chọn cách nào tùy bạn!

Cảm ơn các bạn đã xem! Chúc các bạn học tốt!


Post a Comment

[facebook][blogger]

Contact Form

Name

Email *

Message *

Powered by Blogger.
Javascript DisablePlease Enable Javascript To See All Widget