Trao đổi với tôi

http://www.buidao.com

2/6/18

[Android], Android từ đầu: Hiểu về Adapter và Adapter View

Adapter View ở khắp mọi nơi và bạn sẽ khó mà tìm thấy một ứng dụng Android phổ biến mà không sử dụng chúng. Tên nghe có vẻ lạ, nhưng nếu bạn nghĩ rằng bạn chưa bao giờ nhìn thấy một Adapter View, thì bạn có thể đã sai lầm. Mỗi khi bạn nhìn thấy một ứng dụng Android hiển thị các phần tử của giao diện người dùng dưới dạng một danh sách, một lưới hoặc ngăn xếp, tức là bạn đã nhìn thấy một Adapter View trong thực tế.
Một Adapter View, như tên gọi của nó, là một đối tượng View. Điều này có nghĩa là, bạn có thể thêm nó vào các Activity của bạn theo cùng một cách bạn thêm bất cứ thành phần giao diện người dùng khác. Tuy nhiên, nó không có khả năng hiển thị bất kỳ dữ liệu nào của riêng mình. Nội dung của nó luôn luôn được xác định bởi một đối tượng khác, một Adapter. Trong bài này, tôi sẽ hướng dẫn cho bạn cách làm thế nào để tạo ra các Adapter và sử dụng chúng để tạo ra các loại Adapter View khác nhau chẳng hạn như ListView và GridView.
Một Adapter là một đối tượng của một lớp cài đặt giao diện Adapter. Nó đóng vai trò như là một liên kết giữa một tập hợp dữ liệu và một Adapter View, một đối tượng của một lớp thừa kế lớp trừu tượng AdapterView. Tập hợp dữ liệu có thể là bất cứ điều gì mà trình bày dữ liệu một cách có cấu trúc. Mảng, các đối tượng List và các đối tượng Cursor thường sử dụng bộ dữ liệu.
Một Adapter có trách nhiệm lấy dữ liệu từ bộ dữ liệu và tạo ra các đối tượng View dựa trên dữ liệu đó. Các đối tượng View được tạo ra sau đó được sử dụng để gắn lên bất kỳ Adapter View mà ràng buộc với Adapter
Bạn có thể tạo các lớp Adapter riêng của bạn từ đầu, nhưng hầu hết các nhà phát triển muốn sử dụng hoặc thừa kế các lớp Adapter được cung cấp bởi Android SDK, chẳng hạn như ArrayAdapter và SimpleCursorAdapter. Trong hướng dẫn này, chúng ta sẽ tập trung vào lớp ArrayAdapter.
Adapter View có thể hiển thị các bộ dữ liệu lớn rất hiệu quả. Ví dụ, ListView và GridView có thể hiển thị hàng triệu phần tử mà không có bất cứ độ trễ đáng kể nào trong khi vẫn sử dụng bộ nhớ và CPU rất thấp. Chúng có thể làm điều đó như thế nào? Các Adapter View khác nhau tuân theo những chiến lược khác nhau. Tuy nhiên, đây là những gì mà hầu hết chúng thường làm.
  • Chúng chỉ kết xuất những đối tượng View mà đã trên màn hình hoặc nó đang di chuyển vào màn hình. Bằng cách này, bộ nhớ tiêu thụ bởi một Adapter View có thể được cố định và độc lập với kích thước của tập dữ liệu.
  • Chúng cũng cho phép các nhà phát triển giảm thiểu công sức cho các hoạt động inflate layout và tái sử dụng các đối tượng View sẵn có đã di chuyển khỏi màn. Điều này sẽ giúp tiêu thụ CPU thấp.
Để tạo một Adapter, bạn cần những thứ sau đây:
  • một tập hợp dữ liệu
  • một tập tin có chứa Layout của các đối tượng View được tạo ra
Ngoài ra, vì lớp ArrayAdapter chỉ có thể làm việc với chuỗi, nên bạn cần phải chắc chắn rằng Layout của các đối tượng View được tạo ra có chứa ít nhất một TextView.
Lớp ArrayAdapter có thể sử dụng cả mảng và các đối tượng List như là bộ dữ liệu. Bây giờ, hãy sử dụng một mảng làm tập hợp dữ liệu.
Tạo một tập tin Layout XML mới mà phần tử gốc là một LinearLayout và đặt tên nó là item.xml. Kéo và thả một Large text widget vào trong đó và thiết lập giá trị thuộc tính id của nó thành cheese_name. Tập tin Layout XML sẽ trông như thế này:
Trong Activity của bạn, tạo ra một đối tượng mới của lớp ArrayAdapter bằng cách sử dụng hàm xây dựng của nó. Đối với các đối số của nó, truyền vào tên của tập tin tài nguyên, định danh của TextView, và một tham chiếu đến mảng. Adapter bây giờ đã sẵn sàng.
Để hiển thị một danh sách cuộn theo chiều dọc của các phần tử, bạn có thể sử dụng ListView. Để thêm nó vào Activity của bạn, bạn có thể kéo và thả nó vào trong tập tin layout XML của Activity hoặc tạo ra nó bằng cách sử dụng hàm xây dựng của nó trong code Java của bạn. Bây giờ, chúng ta thực hiện cái thứ hai.
Thông thường, không có các thành phần giao diện người dùng khác được đặt bên trong một Layout có chứa một ListView. Vì vậy, truyền ListView vào phương thức setContentView() của Activity để nó chiếm toàn bộ màn hình.
Để liên kết ListView với Adapter mà chúng ta đã tạo ra ở bước trước đó, hãy gọi phương thức setAdapter()như hình dưới đây.
Nếu bạn chạy ứng dụng của bạn ngay bây giờ, bạn có thể xem nội dung của các mảng ở dạng một danh sách.
ListView With ArrayAdapter
Để hiển thị một danh sách lưới hai chiều cuộn theo chiều dọc của các phần tử, bạn có thể sử dụng GridView. Cả ListView và GridView là lớp con của lớp trừu tượng AbsListView và chúng chia sẻ nhiều điểm tương đồng. Vì vậy, nếu bạn biết cách sử dụng một cái, thì bạn cũng sẽ biết cách sử dụng cái còn lại.
Sử dụng hàm xây dựng của lớp GridView để tạo ra một đối tượng mới và truyền nó vào phương thức setContentView() của Activity.
Để thiết lập số cột trong Grid, hãy gọi phương thức setNumColumns() của nó. Tôi sẽ cho nó hai cột.
Thông thường, bạn sẽ cần điều chỉnh độ rộng của các cột và khoảng cách giữa chúng bằng cách sử dụng các phương thức setColumnWidth()setVerticalSpacing() và setHorizontalSpacing(). Lưu ý rằng những phương thức này sử dụng pixel làm đơn vị của chúng.
Bạn bây giờ có thể buộc GridView vào adapter mà chúng ta đã tạo ra trước đó bằng cách sử dụng phương thức setAdapter().
Chạy lại ứng dụng của bạn một lần nữa để xem GridView trông như thế nào.
GridView With ArrayAdapter
Chúng ta có thể lắng nghe các sự kiện chạm và chạm lâu vào các phần tử bên trong một Adapter View. Ví dụ, hãy thêm một listener sự kiện bấm vào GridView.
Tạo ra một đối tượng mới của một lớp nặc danh cài đặt giao diện AdapterView.OnItemClickListener và truyền nó vào phương thức setOnItemClickListener() của đối tượng GridView. Android Studio tự động tạo ra ngẫu nhiên phương thức onItemClick() của giao diện. Bạn sẽ thấy rằng các tham số của phương thức bao gồm một số nguyên xác định vị trí của phần tử. Bạn có thể sử dụng số nguyên này để tìm thấy phần tử trong bộ dữ liệu mà người dùng đã nhấp vào.
Các code sau đây minh họa cách làm thế nào để hiển thị một thông báo đơn giản mỗi khi một phần tử trong GridView được nhấp.
Nếu bạn chạy ứng dụng và nhấp vào bất kỳ phần tử nào trong Grid, một thông báo sẽ xuất hiện ở dưới cùng của màn hình. Lưu ý rằng bạn có thể sử dụng code tương tự để lắng nghe các sự kiện nhấp lên các phần tử bên trong một ListView.
Snackbar Shown When Items Are Clicked
Một ArrayAdapter chỉ có thể xử lý một TextView bên trong layout của các đối tượng View mà nó tạo ra. Để mở rộng khả năng của nó, bạn phải thừa kế nó. Tuy nhiên, trước khi chúng ta làm điều đó, chúng ta hãy tạo ra một tập hợp dữ liệu phức tạp hơn một chút.
Thay vì chuỗi, giả sử rằng tập hợp dữ liệu của chúng ta có chứa các đối tượng của lớp sau đây:
Đây là tập hợp dữ liệu mà chúng ta sẽ sử dụng:
Như bạn thấy, lớp Cheese có chứa hai trường, name và description. Để hiển thị cả hai trường trong một List hoặc Grid, thì layout của các phần tử phải chứa hai TextView.
Tạo một tập tin layout XML mới và đặt tên là custom_item.xml. Thêm Large text và một Small text vào nó. Thiết lập thuộc tính id của cái đầu tiên thành cheese_name và của cái thứ hai là cheese_description. Nội dung của tập tin layout XML bây giờ sẽ giống như thế này:
ArrayAdapter cũng phải có khả năng xử lý hai TextView. Xem lại Activity của bạn, tạo ra một lớp nặc danh mới thừa kế lớp ArrayAdapter và override phương thức getView() của nó. Hãy chắc chắn rằng bạn truyền mảng như là đối số vào hàm xây dựng của nó.
Bên trong phương thức getView(), bạn phải sử dụng tham số position như là một chỉ số của mảng và lấy phần tử ở chỉ số đó.
Tham số thứ hai của phương thức getView() là những gì cho phép chúng ta tái sử dụng các đối tượng View. Nếu bạn bỏ qua nó, hiệu suất của các adapter view của bạn sẽ thấp. Khi phương thức getView()được gọi lần đầu tiên, thì convertView là null. Bạn phải khởi tạo nó bằng cách inflate tập tin tài nguyên xác định layout của các phần tử. Để làm như vậy, hãy lấy một tham chiếu đến một LayoutInflater bằng cách sử dụng phương thức getLayoutInflater() và gọi phương thức inflate() của nó.
Tại thời điểm này, bạn có thể sử dụng findViewById() để có được một tham chiếu đến các TextView bên trong layout và gọi phương thức setText() để khởi tạo chúng bằng cách sử dụng dữ liệu từ mảng.
Cuối cùng, trả về convertView vì vậy mà nó có thể được sử dụng để đưa bất kỳ adapter view kết hợp với adapter.
Advertisement
Phương thức getView() được gọi liên tục bởi Adapter View để phân phối chính nó. Vì vậy, bạn phải cố gắng giảm thiểu số lượng các hoạt động mà bạn thực hiện bên trong nó.
Ở bước trước, bạn có thể thấy rằng, mặc dù chúng ta đã chắc chắn rằng layout của các phần tử trong danh sách inflate chỉ một lần, nhưng phương thức findViewById(), chiếm nhiều CPU, được gọi mỗi khi phương thức getView() được gọi.
Để tránh điều này và cải thiện hiệu suất của Adapter View, chúng ta cần lưu trữ các kết quả của phương thức findViewById() bên trong đối tượng convertView. Để làm như vậy, chúng ta có thể sử dụng một đối tượng View Holder, nó không có gì khác hơn là một đối tượng của một lớp có thể lưu trữ các thành phần hiện diện trong layout.
Bởi vì layout có hai TextView, nên View Holder cũng phải có hai TextView. Tôi đã đặt tên lớp là ViewHolder.
Trong phương thức getView(), sau khi bạn inflate layout, bây giờ bạn có thể khởi tạo đối tượng View Holder bằng cách sử dụng phương thức findViewById().
Để lưu trữ đối tượng View Holder trong convertView, sử dụng phương thức setTag() của nó.
Và bây giờ, mỗi khi getView() được gọi, bạn có thể lấy đối tượng View Holder từ convertView bằng cách sử dụng phương thức getTag() và cập nhật các TextView bên trong nó bằng cách sử dụng phương thức setText() của chúng.
Nếu bạn chạy ứng dụng của bạn ngay bây giờ, bạn có thể thấy GridView hiển thị hai dòng văn bản trong mỗi ô.
GridView with two lines of text per item
Trong hướng dẫn này, bạn đã biết cách làm thế nào để tạo ra một Adapter và sử dụng nó để phân phối các Adapter View khác nhau. Bạn cũng học được cách tạo Adapter tuỳ biến riêng của bạn. Mặc dù chúng ta chỉ tập trung vào các lớp ArrayAdapterListView và GridView, nhưng bạn có thể sử dụng các kỹ thuật tương tự cho các Adapter và Adapter View mà Android SDK cung cấp.
Android Support Library có bao gồm lớp RecyclerView. Nó hoạt động rất giống một Adapter View, nhưng nó không phải là một lớp con của lớp AdapterView. Bạn nên xem xét việc sử dụng nó nếu bạn muốn tạo các danh sách phức tạp hơn, đặc biệt là những cái mà sử dụng tập tin layout cho các phần của chúng. Để tìm hiểu thêm về nó, bạn có thể tham khảo hướng dẫn này trên Envato Tuts+.
Để tìm hiểu thêm về lớp AdapterView và các lớp con của nó, bạn có thể tham khảo tài liệu hướng dẫn của nó.

Link: https://code.tutsplus.com/vi/tutorials/android-from-scratch-understanding-adapters-and-adapter-views--cms-26646