Tái chế Android vs ListView với Viewholder


148

Gần đây tôi đã bắt gặp Android RecyclerViewđược phát hành với Android 5.0 và dường như đó RecyclerViewchỉ là một truyền thống được gói gọn ListViewvới mẫu ViewHolder được tích hợp vào nó, nhằm thúc đẩy việc sử dụng lại chế độ xem, thay vì tạo ra nó mỗi lần.

Những lợi ích khác của việc sử dụng là RecyclerViewgì? Nếu cả hai đều có cùng hiệu quả về mặt hiệu suất, tại sao người ta lại thích RecyclerView`?

Biên tập

Tôi thấy rằng mọi người đã hỏi câu hỏi tương tự và câu trả lời không có kết luận, thêm chúng vào đây để lưu giữ hồ sơ.

Tái chế vs Listview

Chúng ta có nên sử dụng RecyclerView để thay thế ListView không?

Tại sao RecyclerView không có onItemClickListener ()? và RecyclerView khác với Listview như thế nào?


4
Bởi vì RecyclerViewnhanh hơn và linh hoạt hơn với API tốt hơn nhiều. Những thứ như hoạt hình thêm hoặc loại bỏ các mục đã được thực hiện trong RecyclerViewmà không cần bạn phải làm gì cả. Không có câu hỏi về nó, ném của bạn ListViewvào thùng rác, RecyclerViewlà ở đây để ăn cắp chương trình.
Xaver Kapeller

4
Bạn có thể liên kết trình quản lý bố cục với RecyclerView để chúng không bị giới hạn trong danh sách cuộn theo chiều dọc. Đây là chức năng bổ sung khá mạnh mẽ.
Alan

@Alan - Ý bạn là gì khi "không giới hạn trong danh sách cuộn theo chiều dọc"? Bạn có nói rằng Chế độ xem tái chế cũng có thể đóng vai trò là "trình giữ chỗ" cho Gridview và ListViews không?
Mushtaq Jameel

@XaverKapeller - Sẽ thật tuyệt nếu bạn có thể liệt kê sự khác biệt giữa hai người và trả lời câu hỏi thay vì trên một bình luận, để nó có thể giúp tôi và những người khác trong tương lai có thể tự hỏi về điều tương tự?
Mushtaq Jameel

@Alan - Bạn có thể cung cấp một chút chi tiết về những gì bạn muốn nói và trả lời câu hỏi thay vì trên một bình luận. Cảm ơn bạn đã dành thời gian
Mushtaq Jameel

Câu trả lời:


289

Với sự ra đời của Android Lollipop, RecyclerView đã chính thức đi vào hoạt động. RecyclerView mạnh hơn , linh hoạt hơn và là một cải tiến lớn so với ListView . Tôi sẽ cố gắng cung cấp cho bạn một cái nhìn chi tiết về nó.

1) Mẫu ViewHolder

Trong ListView, nên sử dụng mẫu ViewHolder nhưng nó không bao giờ là bắt buộc. Trong trường hợp RecyclerView, điều này là bắt buộc khi sử dụng lớp RecyclerView.ViewHolder . Đây là một trong những khác biệt chính giữa ListView và RecyclerView.

Nó làm cho mọi thứ phức tạp hơn một chút trong RecyclerView nhưng rất nhiều vấn đề mà chúng tôi gặp phải trong ListView được giải quyết hiệu quả.

2) Trình quản lý bố cục

Đây là một cải tiến lớn khác được mang đến RecyclerView. Trong ListView, loại chế độ xem duy nhất khả dụng là ListView dọc. Không có cách chính thức nào để thực hiện ListView theo chiều ngang.

Bây giờ bằng cách sử dụng RecyclerView, chúng ta có thể có một

i) linearLayoutManager - hỗ trợ cả danh sách dọc và ngang,

ii) StaggeredLayoutManager - hỗ trợ Pinterest như danh sách so le,

iii) GridLayoutManager - hỗ trợ hiển thị các lưới như đã thấy trong các ứng dụng Thư viện.

Và điều tốt nhất là chúng ta có thể làm tất cả những điều này một cách linh hoạt như chúng ta muốn.

3) Mục hoạt hình

ListViews thiếu sự hỗ trợ của hình ảnh động tốt, nhưng RecyclerView mang đến một chiều hướng hoàn toàn mới cho nó. Sử dụng lớp RecyclerView.ItemAnimator , việc tạo hiệu ứng cho các khung nhìn trở nên rất dễ dàng và trực quan.

4) Vật phẩm trang trí

Trong trường hợp ListViews, các mục trang trí động như thêm viền hoặc chia không bao giờ dễ dàng. Nhưng trong trường hợp RecyclerView, lớp RecyclerView.ItemDecorator cung cấp quyền kiểm soát lớn cho các nhà phát triển nhưng làm cho mọi thứ tốn thời gian và phức tạp hơn một chút.

5) OnItemTouchListener

Việc chặn các lần nhấp vào mục trên ListView rất đơn giản, nhờ giao diện AdapterView.OnItemClickListener của nó . Nhưng RecyclerView cung cấp nhiều quyền lực và quyền kiểm soát hơn cho các nhà phát triển của nó bởi RecyclerView.OnItemTouchListener ( Không còn được hỗ trợ, vui lòng tham khảo AndroidX ) nhưng nó làm phức tạp mọi thứ một chút cho nhà phát triển.

Nói một cách đơn giản, RecyclerView có thể tùy biến nhiều hơn so với ListView và mang lại nhiều quyền kiểm soát và sức mạnh cho các nhà phát triển của nó.


34
Câu trả lời tốt. Một vài điểm cộng rất lớn: RecyclerView chuẩn bị chế độ xem ngay phía trước và phía sau các mục hiển thị, điều này thật tuyệt nếu bạn đang tìm nạp bitmap trong nền. Hiệu suất nhanh hơn đáng kể, đặc biệt nếu bạn sử dụng RecyclerView.setHasFixedSize. ListView cũ dựa trên tiền đề rằng không có cách nào để tính toán trước hoặc lưu trữ kích thước của các mục trong danh sách, điều này gây ra các biến chứng điên rồ khi cuộn và thực hiện bố cục. Mất một thời gian để làm quen với nó, nhưng một khi bạn làm thế, bạn sẽ không bao giờ quay lại.
Robin Davies

@RobinDavies Điểm tuyệt vời. Cảm ơn đã thông báo. Nhưng nó sẽ không có ý nghĩa nếu kích thước của các mặt hàng là khác nhau.
Aritra Roy

@AritraRoy Recyclerview chỉ hỗ trợ cho kẹo mút hoặc api 14+ (android 4+)? .... khi tôi đọc "sau kẹo mút: tại hầu hết các địa điểm
Animesh Mangla

2
Này, Aritra, Khi so sánh với ListView, nếu ListView cũng sử dụng Mẫu ViewHolder, cái nào hoạt động hiệu quả hơn? RecylerView sẽ tốt hơn, khi sử dụng khung hình / giây hoặc một số tiêu chí tương tự khác? thx ~
RxRead

@RxRead: Xem bình luận của Robin, anh ấy phân biệt RecyclerView Vs ListView với mẫu giữ khung nhìn trên cơ sở hiệu suất.
Parag Kadam

10

Điểm cộng khác của việc sử dụng RecycleViewlà hình ảnh động, nó có thể được thực hiện trong hai dòng mã

RecyclerView.ItemAnimator itemAnimator = new DefaultItemAnimator();
        recyclerView.setItemAnimator(itemAnimator);

Nhưng tiện ích vẫn còn nguyên, ví dụ: bạn không thể tạo tiêu đềchân trang .


5
Và bạn sẽ không bao giờ có thể tạo tiêu đề và chân trang theo nghĩa đó. Chúng chỉ là các kiểu xem khác trong bộ điều hợp của bạn. Chế độ xem danh sách kết thúc bộ điều hợp của bạn HeaderViewListAdaptervà thêm hỗ trợ tiêu đề trong nền. Với RecyclerViewbạn là người kiểm soát.
Eugen Pechanec

RecyclerView sử dụng DefaultItemAnimator theo mặc định. Vậy thì tại sao bạn lại sử dụng mã này?
Athira Reddy

9

Được rồi, một chút đào và tôi đã tìm thấy những viên đá quý từ bài viết của Bill Philips trênRecycleView

RecyclerView có thể làm nhiều hơn ListView, nhưng bản thân lớp RecyclerView có ít trách nhiệm hơn ListView. Ra khỏi hộp, RecyclerView không:

  • Mục mục trên màn hình
  • Quan điểm sống động
  • Xử lý mọi sự kiện chạm ngoài việc cuộn

Tất cả những thứ này đã được đưa vào ListView, nhưng RecyclerView sử dụng các lớp cộng tác viên để thực hiện các công việc này thay thế.

ViewHolders bạn tạo cũng mạnh mẽ hơn. Chúng phân lớp RecyclerView.ViewHolder, trong đó có một loạt các phương thức RecyclerView sử dụng. ViewHoldersbiết vị trí nào họ hiện đang bị ràng buộc, cũng như id mục nào (nếu bạn có những vị trí đó). Trong quá trình, ViewHolder đã được phong tước hiệp sĩ. Nó từng là công việc của ListView để giữ toàn bộ chế độ xem mục và ViewHolderchỉ được giữ trên các phần nhỏ của nó.

Bây giờ, ViewHolder giữ tất cả trong ViewHolder.itemView trường, được gán trong hàm tạo của ViewHolder cho bạn.


4

Thông tin thêm từ bài viết của Bill Phillip (hãy đọc nó!) Nhưng tôi nghĩ điều quan trọng là chỉ ra những điều sau đây.

Trong ListView, có một sự mơ hồ về cách xử lý các sự kiện nhấp chuột: Các chế độ xem riêng lẻ nên xử lý các sự kiện đó hay ListView nên xử lý chúng thông qua OnItemClickListener? Tuy nhiên, trong RecyclerView, ViewHolder ở vị trí rõ ràng để hoạt động như một đối tượng điều khiển mức hàng xử lý các loại chi tiết đó.

Chúng tôi đã thấy trước đó là LayoutManager xử lý các chế độ xem định vị và ItemAnimator xử lý hoạt ảnh chúng. ViewHolder là phần cuối cùng: nó chịu trách nhiệm xử lý mọi sự kiện xảy ra trên một mục cụ thể mà RecyclerView hiển thị.


2

Tôi đã sử dụng một ListViewtrình tải hình ảnh Glide, có sự tăng trưởng bộ nhớ. Sau đó, tôi thay thế ListViewbằng a RecyclerView. Nó không chỉ khó khăn hơn trong mã hóa, mà còn dẫn đến việc sử dụng bộ nhớ nhiều hơn a ListView. Ít nhất, trong dự án của tôi.

Trong một hoạt động khác, tôi đã sử dụng một danh sách phức tạp với EditText's. Trong một số phương thức, một phương thức nhập liệu có thể khác nhau, cũng TextWatchercó thể được áp dụng. Nếu tôi đã sử dụng một ViewHolder, làm thế nào tôi có thể thay thế TextWatchertrong khi cuộn? Vì vậy, tôi đã sử dụng ListViewmà không có a ViewHolder, và nó hoạt động.


Tôi đã sử dụng ListView mà không có ViewHolder và nó hoạt động. ý tưởng khủng khiếp ... làm thế nào tôi có thể thay thế TextWatcher trong khi cuộn? không cần phải thay thế nó ... chỉ cần TextWacher nên đưa dữ liệu vào các thùng chứa khác nhau sau khi sử dụng lại ... và nó có thể được thực hiện rất dễ dàng
Selvin

@Selvin, cảm ơn ý kiến ​​của bạn. Bây giờ tôi không thể chỉnh sửa dự án đó. Có một vài TextWatchers trên màn hình. Có lẽ bạn đúng, nhưng tôi không thể kiểm tra nó.
CoolMind

1

Sử dụng lại các ô trong khi cuộn lên / xuống - điều này có thể với việc triển khai Chế độ xem trong bộ điều hợp listView, nhưng đó là một tùy chọn, trong khi trong RecyclView, đó là cách viết bộ điều hợp mặc định.

Liệt kê danh sách từ bộ chứa của nó - vì vậy bạn có thể dễ dàng đặt các mục danh sách trong thời gian chạy vào các bộ chứa khác nhau (linearLayout, GridLayout) với cài đặt LayoutManager.

Thí dụ:

mRecyclerView = (RecyclerView) findViewById(R.id.recycler_view);
mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
//or
mRecyclerView.setLayoutManager(new GridLayoutManager(this, 2));
mRecyclerView.setLayoutManager(new GridLayoutManager(this, 3));
  • Hoạt hình danh sách hành động phổ biến.

  • Ảnh động được tách rời và ủy thác ItemAnimator.

Có nhiều hơn về RecyclerView, nhưng tôi nghĩ những điểm này là những điểm chính.

Trình quản lý bố cục

i) linearLayoutManager - hỗ trợ cả danh sách dọc và ngang,

ii) StaggeredLayoutManager - hỗ trợ Pinterest như danh sách so le,

iii) GridLayoutManager - hỗ trợ hiển thị các lưới như đã thấy trong các ứng dụng Thư viện.

Và điều tốt nhất là chúng ta có thể làm tất cả những điều này một cách linh hoạt như chúng ta muốn.


1

1. Xem chủ sở hữu

Trong ListView, xác định chủ sở hữu chế độ xem là cách tiếp cận được đề xuất để giữ tham chiếu cho chế độ xem. Nhưng nó không phải là một sự ép buộc. Mặc dù không làm như vậy, ListView đã sử dụng hiển thị dữ liệu cũ. Một nhược điểm lớn khác của việc không sử dụng chủ sở hữu chế độ xem có thể dẫn đến một hoạt động nặng nề là tìm kiếm lượt xem theo id mỗi lần. Điều này dẫn đến ListViews lag.

Vấn đề này được giải quyết trong RecylerView bằng cách sử dụng lớp RecyclerView.ViewHolder. Đây là một trong những khác biệt chính trong RecyclerView và ListView. Khi triển khai RecyclerView, lớp này được sử dụng để xác định một đối tượng ViewHolder được bộ điều hợp sử dụng để liên kết ViewHolder với một vị trí. Một điểm khác cần lưu ý ở đây là trong khi triển khai bộ điều hợp cho RecyclerView, việc cung cấp ViewHolder là bắt buộc. Điều này làm cho việc triển khai hơi phức tạp, nhưng giải quyết được các vấn đề gặp phải trong ListView.

2. Trình quản lý bố cục

Khi nói về ListView, chỉ có một loại ListView có sẵn, tức là ListView dọc. Bạn không thể triển khai ListView với cuộn ngang. Tôi biết có nhiều cách để thực hiện cuộn ngang, nhưng tôi tin rằng nó không được thiết kế để hoạt động theo cách đó.

Nhưng bây giờ khi chúng ta xem xét Android RecyclerView vs ListView, chúng ta cũng có hỗ trợ cho các bộ sưu tập theo chiều ngang. Trong thực tế, nó hỗ trợ nhiều loại danh sách. Để hỗ trợ nhiều loại danh sách, nó sử dụng lớp RecyclerView.LayoutManager. Đây là một cái gì đó mới mà ListView không có. RecyclerView hỗ trợ ba loại Trình quản lý bố cục được xác định trước:

LinearLayoutManager - Đây là trình quản lý bố cục được sử dụng phổ biến nhất trong trường hợp RecyclerView. Thông qua đó, chúng ta có thể tạo cả danh sách cuộn ngang và dọc. StaggeredGridLayoutManager - Thông qua trình quản lý bố cục này, chúng tôi có thể tạo danh sách so le. Giống như màn hình Pinterest. GridLayoutManager MySpace Trình quản lý bố cục này có thể được sử dụng để hiển thị các lưới, giống như bất kỳ thư viện ảnh nào.

3. Mục hoạt hình

Ảnh động trong một danh sách là một chiều hoàn toàn mới, có khả năng vô tận. Trong một ListView, như vậy, không có quy định đặc biệt nào thông qua đó người ta có thể làm động, thêm hoặc xóa các mục. Thay vào đó, sau này khi Android tiến hóa ViewPropertyAnimator được đề xuất bởi Google Chet Haase trong hướng dẫn bằng video này cho hoạt hình trong ListView.

Mặt khác, so sánh Android RecyclerView với ListView, nó có lớp RecyclerView.ItemAnimator để xử lý hình ảnh động. Thông qua lớp này, hình ảnh động tùy chỉnh có thể được xác định để thêm các mục, xóa và di chuyển các sự kiện. Ngoài ra, nó cung cấp một DefaultItemAnimator, trong trường hợp bạn không cần bất kỳ tùy chỉnh nào.

4. Bộ chuyển đổi

Bộ điều hợp ListView rất đơn giản để thực hiện. Họ đã có một phương thức chính getView nơi tất cả các phép thuật đã từng xảy ra. Nơi các quan điểm bị ràng buộc vào một vị trí. Ngoài ra, họ từng có một phương thức thú vị registerDataSetObserver nơi người ta có thể đặt một người quan sát ngay trong bộ điều hợp. Tính năng này cũng có trong RecyclerView, nhưng lớp RecyclerView.Ad CHƯƠNGDataObserver được sử dụng cho nó. Nhưng điểm có lợi cho ListView là nó hỗ trợ ba triển khai bộ điều hợp mặc định:

ArrayAd CHƯƠNG CthonAd Module SimpleCthonAdRAM Trong khi bộ điều hợp RecyclerView, có tất cả các chức năng mà các bộ điều hợp ListView có ngoại trừ hỗ trợ tích hợp cho con trỏ DB và ArrayLists. Hiện tại, trong RecyclerView.Ad CHƯƠNG chúng ta phải thực hiện tùy chỉnh để cung cấp dữ liệu cho bộ điều hợp. Giống như BaseAd CHƯƠNG làm cho ListViews. Mặc dù nếu bạn muốn biết thêm về triển khai bộ điều hợp RecyclerView, vui lòng tham khảo Ví dụ về RecyclerView của Android.

5. Thông báo thay đổi dữ liệu

Khi làm việc với ListView, nếu bộ dữ liệu bị thay đổi, bạn phải gọi phương thức notifyDataSetChanged của bộ điều hợp cơ bản để làm mới dữ liệu. Hoặc đặt phương thức setNotifyOnChange thành true trong trường hợp bạn muốn tự động gọi phương thức notifyDataSetChanged. Nhưng trong cả hai trường hợp, đi ra là rất nặng trong danh sách. Về cơ bản nó làm mới quan điểm của danh sách.

Nhưng ngược lại trong bộ điều hợp RecyclerView, nếu một mục duy nhất hoặc một phạm vi các mục đã thay đổi, có các phương pháp để thông báo thay đổi tương ứng. Đó là notifyItemChanged và notifyItemRangeChanged và nhiều hơn nữa như:

notifyItemInsterted notifyItemMoved notifyItemRangeInsterted notifyItemRangeRemond Và tất nhiên nó có phương thức ban đầu để làm mới toàn bộ danh sách tức là notifyDataSetChanged thông báo toàn bộ tập dữ liệu đã thay đổi.

6. Vật phẩm trang trí

Để hiển thị các bộ chia tùy chỉnh trong ListView, người ta có thể dễ dàng thêm các tham số này trong ListView XML:

XHTML android: spliter = "@ android: color / suốt" cho đến bây giờ nó không hiển thị một bộ chia giữa các mục theo mặc định. Mặc dù những kẻ ở Google phải bỏ cái này ra để tùy chỉnh, cố ý. Nhưng điều này làm tăng đáng kể nỗ lực cho một nhà phát triển. Nếu bạn muốn thêm một bộ chia giữa các mục, bạn có thể cần thực hiện tùy chỉnh bằng cách sử dụng lớp RecyclerView.ItemDecoration.

Hoặc bạn có thể áp dụng hack bằng cách sử dụng tệp này từ các mẫu chính thức: DividerItemDecor.java

7. OnItemTouchListener

Danh sách được sử dụng để thực hiện đơn giản để phát hiện các nhấp chuột, tức là bằng cách sử dụng giao diện AdapterView.OnItemClickListener.

Nhưng mặt khác, giao diện RecyclerView.OnItemTouchListener được sử dụng để phát hiện các sự kiện chạm trong Android RecyclerView. Nó làm phức tạp việc thực hiện một chút, nhưng nó mang lại sự kiểm soát lớn hơn cho nhà phát triển để chặn các sự kiện chạm. Các tài liệu chính thức nêu rõ, nó có thể hữu ích cho các thao tác cử chỉ vì nó chặn một sự kiện chạm trước khi nó được gửi đến RecyclerView.


1

RecyclerView được tạo như một cải tiến ListView, vì vậy, bạn có thể tạo một danh sách đính kèm với điều khiển ListView, nhưng sử dụng RecyclerView thì dễ dàng hơn:

  1. Sử dụng lại các ô trong khi cuộn lên / xuống : điều này có thể với việc triển khai Chế độ xem trong bộ điều hợp ListView, nhưng đó là một tùy chọn, trong khi trong RecyclView, đó là cách viết bộ điều hợp mặc định.

  2. Liệt kê danh sách từ bộ chứa của nó : vì vậy bạn có thể dễ dàng đặt các mục danh sách trong thời gian chạy vào các bộ chứa khác nhau (linearLayout, GridLayout) với cài đặt LayoutManager.

mRecyclerView = (RecyclerView) findViewById (R.id.my_recycler_view); mRecyclerView.setLayoutManager (linearLayoutManager mới (này)); mRecyclerView.setLayoutManager (GridLayoutManager mới (này, 2));

  1. Hoạt hình danh sách hành động phổ biến : Ảnh động được tách rời và ủy quyền cho ItemAnimator. Có nhiều hơn về RecyclerView, nhưng tôi nghĩ những điểm này là những điểm chính.

Vì vậy, để kết luận, RecyclerView là một điều khiển linh hoạt hơn để xử lý "danh sách dữ liệu" theo mô hình của mối quan tâm và chỉ để lại một nhiệm vụ - tái chế các mục.


0

Nếu bạn sử dụng RecyclView, trước tiên bạn cần thêm efford để thiết lập. Bạn cần cho thêm thời gian để thiết lập Item đơn giản onclick, viền, sự kiện chạm và những thứ đơn giản khác. Nhưng sản phẩm cuối cùng sẽ hoàn hảo.

Vì vậy, quyết định là của bạn. Tôi đề nghị, nếu bạn thiết kế ứng dụng đơn giản như tải danh bạ, trong đó nhấp chuột đơn giản là đủ, bạn có thể triển khai listview. Nhưng nếu bạn thiết kế như trang chủ phương tiện truyền thông xã hội với cuộn không giới hạn. Một số trang trí khác nhau giữa các mục, kiểm soát nhiều mục riêng lẻ hơn sử dụng chế độ xem tái chế.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.