Tôi có một trình xem với nhiều kiểu khung nhìn.RecyclerView onBindViewHolder chỉ được gọi khi các thay đổi getItemViewType
Khi cuộn onBindViewHolder
chỉ được gọi khi giá trị thay đổi getItemViewType
. Điều này làm cho các mục danh sách của tôi không được cập nhật đúng cách.
Đây có phải là lỗi không? Hoặc tôi đang làm điều gì sai ở đây. Hành vi này có vẻ rất lạ từ lớp recyclerView
mới.
Đây là bộ chuyển đổi của tôi:
package se.davison.smartrecycleradapter;
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.util.Log;
import android.util.SparseIntArray;
import android.view.LayoutInflater;
import android.view.ViewGroup;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
/**
* Created by richard on 10/11/14.
*/
public class SectionAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private static final String TAG = SectionAdapter.class.getSimpleName();
private final LayoutInflater inflater;
private final int sectionLayoutId;
private SparseIntArray positionSection;
private LinkedHashMap<AdapterItem, List<AdapterItem>> items = new LinkedHashMap<AdapterItem, List<AdapterItem>>();
private List<Class<? extends AdapterItem>> itemTypes = new ArrayList<Class<? extends AdapterItem>>(20);
public SectionAdapter(Context context, int sectionLayoutId, LinkedHashMap<AdapterItem, List<AdapterItem>> items) {
this.inflater = LayoutInflater.from(context);
this.sectionLayoutId = sectionLayoutId;
this.items = items;
initList(items);
}
public SectionAdapter(Context context, int sectionLayoutId) {
this.inflater = LayoutInflater.from(context);
this.sectionLayoutId = sectionLayoutId;
this.items = new LinkedHashMap<AdapterItem, List<AdapterItem>>();
initList(items);
}
@Override
public int getItemViewType(int position) {
AdapterItem item = getItem(position);
Log.d(TAG, position + ": class " + item.getClass());
return itemTypes.indexOf(item.getClass());
}
@Override
public int getItemCount() {
int count = 0;
if (items == null) {
return 0;
}
for (AdapterItem key : items.keySet()) {
count++;
List<AdapterItem> childItems = items.get(key);
if (childItems != null) {
count += childItems.size();
}
}
return count;
}
private void initList(HashMap<AdapterItem, List<AdapterItem>> items) {
positionSection = new SparseIntArray(items.size());
int count = 0;
int sectionIndex = -1;
for (AdapterItem key : items.keySet()) {
Class headerClass = key.getClass();
if (!itemTypes.contains(headerClass)) {
itemTypes.add(headerClass);
}
List<AdapterItem> childItems = items.get(key);
sectionIndex = count;
if (childItems != null) {
for (AdapterItem item : childItems) {
Class clazz = item.getClass();
if (!itemTypes.contains(clazz)) {
itemTypes.add(clazz);
}
positionSection.put(count, sectionIndex);
count++;
}
}
count++;
}
setHasStableIds(true);
}
private AdapterItem getItem(int position) {
int totalChildCount = 0;
int separatorCount = 0;
for (AdapterItem key : items.keySet()) {
if (position == 0 || position == totalChildCount + separatorCount) {
return key;
}
separatorCount++;
List<AdapterItem> list = items.get(key);
int couldCount = countList(list);
if (position < totalChildCount + separatorCount + couldCount) {
return list.get(position - (totalChildCount + separatorCount));
}
totalChildCount += couldCount;
}
return null;
}
public void setItems(LinkedHashMap<AdapterItem, List<AdapterItem>> items) {
this.items = items;
notifyDataSetChanged();
}
public void setItemsAtHeader(int id, List<AdapterItem> items) {
AdapterItem header = null;
for (AdapterItem key : this.items.keySet()) {
if (key.headerId() == id) {
header = key;
break;
}
}
if (header == null) {
throw new IllegalArgumentException(String.format("No header with id %s is found", id));
}
setItemsAtHeader(header, items);
}
private void setItemsAtHeader(AdapterItem header, List<AdapterItem> items) {
this.items.put(header, items);
}
private int countList(List<?> list) {
return list == null ? 0 : list.size();
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
AdapterItem firstItem = getFirstItemWithClass(itemTypes.get(viewType));
return firstItem.onCreateViewHolder(inflater, viewGroup);
}
private AdapterItem getFirstItemWithClass(Class<? extends AdapterItem> clazz) {
for (AdapterItem key : items.keySet()) {
if (key.getClass() == clazz) {
return key;
}
List<AdapterItem> childItems = items.get(key);
if (childItems != null) {
for (AdapterItem item : childItems) {
if (item.getClass() == clazz) {
return item;
}
}
}
}
throw new IllegalStateException("Something is wrong, you dont have any items with that class in your list");
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int position) {
AdapterItem item = getItem(position);
Log.d(TAG, "ITEM = " + item.getClass().getSimpleName());
Log.d(TAG, "POS = " + position);
if (item instanceof OneLineAdapterItem) {
Log.d(TAG, "TEXT = " + ((OneLineAdapterItem) item).getText());
}
item.onBindViewHolder(viewHolder, position);
}
}
Tôi cũng đã trừu tượng hóa ra các mục như sau:
public abstract class AdapterItem<VH extends RecyclerView.ViewHolder> {
public boolean isHeader(){
return false;
}
public int headerId(){
return -1;
}
public abstract VH onCreateViewHolder(LayoutInflater inflater, ViewGroup parent);
public abstract void onBindViewHolder(VH viewHolder, int position);
}
Và đối với phần
public class SectionAdapterItem extends AdapterItem<SectionAdapterItem.ViewHolder> {
private String text;
private boolean dividerVisible = false;
public static class ViewHolder extends RecyclerView.ViewHolder{
TextView titel;
ImageView divider;
public ViewHolder(View itemView) {
super(itemView);
titel = (TextView) itemView.findViewById(android.R.id.title);
divider = (ImageView) itemView.findViewById(android.R.id.icon);
}
}
public void setDividerVisible(boolean dividerVisible) {
this.dividerVisible = dividerVisible;
}
public boolean isDividerVisible() {
return dividerVisible;
}
@Override
public boolean isHeader() {
return true;
}
@Override
public int headerId() {
return super.headerId();
}
public SectionAdapterItem(String text) {
this.text = text;
}
@Override
public ViewHolder onCreateViewHolder(LayoutInflater inflater, ViewGroup parent) {
return new ViewHolder(inflater.inflate(R.layout.top_header, parent, false));
}
@Override
public void onBindViewHolder(ViewHolder viewHolder, int position) {
viewHolder.titel.setText(text);
viewHolder.divider.setVisibility(dividerVisible?View.VISIBLE:View.GONE);
}
}
Nó hoạt động tốt cho But hàng có thể nhìn thấy, nhưng sau đó nó không thành công.
ý bạn là gì bởi onBind không bao giờ được gọi? Điều gì sẽ xảy ra thay vào đó, nó không hiển thị bất cứ điều gì? Cuộn dừng? – yigit
@yigit các mục đầu tiên được hiển thị đúng cách. Nhưng khi tôi bắt đầu di chuyển các mục của tôi chỉ là tái chế để dữ liệu của họ không được cập nhật kể từ onBind không nhận được gọi cho mỗi hàng khi tôi di chuyển. Tôi sẽ sớm thêm một vài ảnh chụp màn hình! – Richard
đối với tôi, đây là vấn đề. http://stackoverflow.com/a/29162119/371749 – cV2