当试图将视图类型作为数组中数据位置的函数返回时,我将获得一个IndexOutOfBoundsException。我有两个数据来源。一个是广告,另一个是名字和地点的列表。在RecyclerAdapter中处理数组之前,是否需要将数组组合成一个数组?我宁愿不这样做,尤其是在原则上它们可以是不同的类型,即图像和文本。我的getItemCount()方法正确地返回两个数组的总和大小。我为什么要得到这个例外?如何在两种不同的视图类型中显示来自两个不同源的数据?
我的主要活动:
public class MainActivity extends AppCompatActivity {
private ArrayList<Object> getPresidentsArrayList() {
ArrayList<Object> items = new ArrayList<>();
items.add(new President("George Washington", "Mount Vernon"));
items.add(new President("John Adams", "Braintree"));
items.add(new President("Thomas Jefferson", "Monticello"));
items.add(new President("James Madison", "Port Conway"));
return items;
}
private ArrayList<Object> getAdsArrayList() {
ArrayList<Object> ads = new ArrayList<>();
ads.add(new Sponsored("Craft Beer 20% Off", "Budweiser"));
ads.add(new Sponsored("Craft Beer 20% Off", "Budweiser"));
ads.add(new Sponsored("Craft Beer 20% Off", "Budweiser"));
ads.add(new Sponsored("Craft Beer 20% Off", "Budweiser"));
return ads;
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recyclerView);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
bindDataToAdapter(recyclerView);
}
private void bindDataToAdapter(RecyclerView recyclerView) {
recyclerView.setAdapter(new HeterogeneousRecyclerAdapter(getPresidentsArrayList(), getAdsArrayList()));
}
}我的回收器适配器允许多个视图:
public class HeterogeneousRecyclerAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private List<Object> items;
private List<Object> ads;
private final int PRESIDENT = 0, SPONSORED = 1;
public HeterogeneousRecyclerAdapter(List<Object> items, List<Object> ads) {
this.items = items;
this.ads = ads;
}
@Override
public int getItemCount() {
return (this.items.size() + this.ads.size());
}
@Override
public int getItemViewType(int position) {
if (items.get(position) instanceof President) {
return PRESIDENT;
} else if (ads.get(position) instanceof Sponsored) {
return SPONSORED;
}
return -1;
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup viewGroup, int viewType) {
RecyclerView.ViewHolder viewHolder;
LayoutInflater inflater = LayoutInflater.from(viewGroup.getContext());
switch (viewType) {
case PRESIDENT:
View v1 = inflater.inflate(R.layout.layout_viewholder1, viewGroup, false);
viewHolder = new ViewHolder1(v1);
break;
case SPONSORED:
View v2 = inflater.inflate(R.layout.layout_viewholder2, viewGroup, false);
viewHolder = new ViewHolder2(v2);
break;
default:
View v = inflater.inflate(android.R.layout.simple_list_item_1, viewGroup, false);
viewHolder = new RecyclerViewSimpleTextViewHolder(v);
break;
}
return viewHolder;
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder viewHolder, int position) {
switch (viewHolder.getItemViewType()) {
case PRESIDENT:
ViewHolder1 vh1 = (ViewHolder1) viewHolder;
configureViewHolder1(vh1, position);
break;
case SPONSORED:
ViewHolder2 vh2 = (ViewHolder2) viewHolder;
configureViewHolder2(vh2, position);
break;
default:
RecyclerViewSimpleTextViewHolder vh = (RecyclerViewSimpleTextViewHolder) viewHolder;
configureDefaultViewHolder(vh, position);
break;
}
}
private void configureDefaultViewHolder(RecyclerViewSimpleTextViewHolder vh, int position) {
vh.getLabel().setText((CharSequence) items.get(position));
}
private void configureViewHolder1(ViewHolder1 vh1, int position) {
President president = (President) items.get(position);
if (president != null) {
vh1.getLabel1().setText(president.getName());
vh1.getLabel2().setText(president.getHometown());
}
}
private void configureViewHolder2(ViewHolder2 vh2, int position) {
Sponsored sponsored = (Sponsored) ads.get(position);
if (sponsored != null) {
vh2.getLabel1().setText(sponsored.getName());
vh2.getLabel2().setText(sponsored.getCompany());
}
}
}发布于 2016-07-04 12:59:05
您需要创建一个公共列表,同时添加两个列表。做以下几件事-
public HeterogeneousRecyclerAdapter(List<Object> items, List<Object> ads) {
this.items = items;
items.addAll(ads);
}现在更改get项目计数-
@Override
public int getItemCount() {
return this.items.size();
}希望它对你会很好:)
发布于 2016-07-04 12:56:44
getItemCount的实现是错误的
@Override
public int getItemCount() {
return (this.items.size() + this.ads.size());
}如果两者都不返回0,则返回的值大于两个集合的大小。这就是为什么你要得到一个ArrayIndexOutBoundException。请记住,position从0到getItemCount - 1,在您的示例中,items和ads都不包含getItemCount对象。
发布于 2016-07-04 13:04:01
getItemViewType的实现是错误的。让我们假设您的items列表有4个条目,ads有3个广告对象。现在您的getItemViewType将返回7。现在系统将开始查找这7个对象的项目类型。让我们假设它希望在RecyclerView中找到第5行的类型。现在,在您的方法中,getItemViewType第1行本身抛出了这个异常,因为items列表的大小仅为4。
要么你必须将这两个列表合并在一个列表中,要么在回收商的视图中有一些订单,就像所有的广告都会出现在物品之前。在这种情况下,您还必须修改getItemViewType。
希望这能有所帮助。
https://stackoverflow.com/questions/38185274
复制相似问题