2014-10-29 19 views
34

Tôi muốn triển khai chức năng tìm kiếm cho RecyclerView của mình. Trên văn bản thay đổi tôi muốn thay đổi dữ liệu được hiển thị với tiện ích này. Có lẽ câu hỏi này đã được hỏi trước hoặc là đơn giản, nhưng tôi không biết làm thế nào sự thay đổi dữ liệu mà là để được hiển thị ...Bộ dữ liệu thay đổi RecyclerView

RecyclerView My được định nghĩa như sau:

 // 1. get a reference to recyclerView 
    mRecyclerView = (RecyclerView)findViewById(R.id.recyclerView); 

    // 2. set layoutManger 
    mRecyclerView.setLayoutManager(new LinearLayoutManager(this)); 
    // 3. create an adapter 
    mAdapter = new ItemsAdapter(itemsData); 
    // 4. set adapter 
    mRecyclerView.setAdapter(mAdapter); 

Và dữ liệu mà tôi đang hiển thị giống như:

ItemData itemsData[] = { new ItemData("Mary Richards"), 
     new ItemData("Tom Brown"), 
     new ItemData("Lucy London")   
}; 

Vì vậy, khi tôi muốn cung cấp cho bộ điều hợp một bộ dữ liệu khác, tôi nên làm gì?

+0

Nếu bạn muốn cho một mảng bạn chỉ có thể tạo ra một mới 'ItemsAdapter' với nó và gọi' setAdapter' một lần nữa. –

Trả lời

74

Nếu bạn có id ổn định trong bộ chuyển đổi, bạn có thể có được kết quả khá tốt (hình ảnh động) nếu bạn tạo một mảng mới có chứa các mục lọc và gọi

recyclerView.swapAdapter(newAdapter, false); 

Sử dụng swapAdapter gợi ý RecyclerView rằng nó có thể tái sử dụng chủ sở hữu xem. (vs trong setAdapter, nó phải tái chế tất cả các khung nhìn và tạo lại vì nó không biết rằng bộ điều hợp mới có cùng một ViewHolder được thiết lập với bộ điều hợp cũ).

Cách tiếp cận tốt hơn là tìm ra mục nào bị xóa và gọi notifyItemRemoved(index). Đừng quên để thực sự loại bỏ các mục. Điều này sẽ cho phép RecyclerView chạy các hình ảnh động tiên đoán. Giả sử bạn có một Adaptor rằng trong nội bộ sử dụng một ArrayList, thực hiện sẽ trông như thế này:

// adapter code 
final List<ItemData> mItems = new ArrayList(); //contains your items 
public void filterOut(String filter) { 
    final int size = mItems.size(); 
    for(int i = size - 1; i>= 0; i--) { 
     if (mItems.get(i).test(filter) == false) { 
      mItems.remove(i); 
      notifyItemRemoved(i); 
     } 
    } 
} 

Nó sẽ thực hiện tốt hơn nếu bạn có thể hàng loạt notifyItemRemoved cuộc gọi và sử dụng notifyItemRangeRemoved để thay thế. Nó sẽ trông sth như: (không kiểm tra)

public void filterOut(String filter) { 
    final int size = mItems.size(); 
    int batchCount = 0; // continuous # of items that are being removed 
    for(int i = size - 1; i>= 0; i--) { 
     if (mItems.get(i).test(filter) == false) { 
      mItems.remove(i); 
      batchCount ++; 
     } else if (batchCount != 0) { // dispatch batch 
      notifyItemRangeRemoved(i + 1, batchCount); 
      batchCount = 0; 
     } 
    } 
    // notify for remaining 
    if (batchCount != 0) { // dispatch remaining 
     notifyItemRangeRemoved(0, batchCount); 
    } 
} 

Bạn cần phải mở rộng đoạn mã này để thêm các mục mà trước đây được lọc ra nhưng bây giờ sẽ được hiển thị (ví dụ người dùng xóa các truy vấn lọc) nhưng tôi nghĩ cái này nên đưa ra ý tưởng cơ bản.

Hãy nhớ rằng, mỗi cuộc gọi mục thông báo sẽ ảnh hưởng đến những cuộc gọi sau đó (đó là lý do tôi duyệt qua danh sách từ đầu để tránh nó). Traversing từ kết thúc cũng giúp ArrayList loại bỏ hiệu suất phương pháp (ít mục để thay đổi). Ví dụ: nếu bạn đang duyệt qua danh sách từ đầu và xóa hai mục đầu tiên. Bạn nên hoặc gọi

notifyItemRangeRemoved(0, 2); // 2 items starting from index 0 

hoặc nếu bạn gửi cho họ từng người một

notifyItemRemoved(0); 
notifyItemRemoved(0);//because after the previous one is removed, this item is at position 0 
+0

Cảm ơn bạn đã phản hồi, tôi sẽ thực hiện những điều chỉnh phù hợp với nhu cầu của tôi, nhưng đây là những gì tôi cần về cơ bản. Bạn giải thích nó rất tốt. – Sandra

+1

"Id ổn định" có nghĩa là gì? Dữ liệu của tôi thay đổi nhưng tôi không biết theo cách nào (một số mục mới có thể được thêm vào và một số có thể bị xóa) nhưng chế độ xem vẫn như cũ, vì vậy tôi có nên chuyển đúng hay sai sang swapAdapter không? –

2

Chỉ cần tái khởi adapter của bạn:

mAdapter = new ItemsAdapter (newItemsData);

hoặc nếu bạn chỉ cần phải loại bỏ thêm một vài mặt hàng cụ thể chứ không phải là một danh sách toàn bộ:

mAdapter. notifyItemInserted (vị trí);

hoặc

mAdapter.notiftyItemRemoved (vị trí);

22

Đây là câu trả lời của tôi - nhờ Ivan Skoric từ trang web của mình: http://blog.lovelyhq.com/creating-lists-with-recyclerview-in-android/

Tôi tạo ra một phương pháp thêm bên trong lớp bộ điều hợp của tôi:

public void updateList(List<Data> data) { 
    mData = data; 
    notifyDataSetChanged(); 
} 

Sau đó, mỗi lần y dữ liệu của chúng tôi thay đổi, bạn chỉ cần gọi phương thức này chuyển vào dữ liệu mới của bạn và chế độ xem của bạn sẽ thay đổi để phản ánh nó.

+0

notifyDataSetChanged() giết tất cả các hoạt ảnh, chỉ tốt cho các danh sách lớn. – Davidea

+0

@Davidea ... đó là trường hợp sử dụng điển hình của RecyclerView –

+0

Recyclerview chỉ giữ các chế độ xem hiển thị của bạn trong bộ nhớ và giải phóng chúng khi bạn cuộn chúng ra khỏi màn hình. Nó là hiệu quả cao từ một góc độ bộ nhớ so với một listview. Chúng hoạt động tương tự như một listview. Bạn có thể đọc tài liệu recyclerview tại đây: https://developer.android.com/reference/android/support/v7/widget/RecyclerView.html – Simon

0

ygit được trả lời, swapAdapter thật thú vị khi bạn phải thay đổi toàn bộ nội dung.

Nhưng, trong FlexibleAdapter, bạn có thể cập nhật các mục với updateDataSet. Bạn thậm chí có thể định cấu hình bộ điều hợp để gọi notifyDataSetChanged hoặc có hình động đồng bộ hóa (được bật theo mặc định). Điều đó, bởi vì notifyDataSetChanged giết tất cả các hình động, nhưng nó là tốt để có cho các danh sách lớn.

hãy có một cái nhìn tại các mô tả, demoApp và Wiki trang: https://github.com/davideas/FlexibleAdapter

Các vấn đề liên quan