为什么 RecyclerView 的 onBindViewHolder 只被调用一次?

12

我的代码出现了一个奇怪的错误。我使用了Recycler View(以前也用过,没有任何问题)。我创建了一个测试ArrayList,想在Recycler View中展示它,但我只得到了第一行,然后应用程序停止运行(不会崩溃),就好像ArrayList已经结束了。

我的主要代码:

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    View view =  inflater.inflate(R.layout.fragment_all_tab, container, false);

    Activity activity = getActivity();

    //TODO: For testing ONLY
    ArrayList<Order> orders = new ArrayList<>();
    for(int i = 0; i < 10; i++) {
        orders.add(new Order(i, i, i));
    }

    // Initialising Orders Recycler View.
    OrderAdapter orderAdapter = new OrderAdapter(activity, orders);
    RecyclerView recyclerViewOrders = (RecyclerView) view.findViewById(R.id.recylerViewAllDiners);
    recyclerViewOrders.setLayoutManager(new LinearLayoutManager(activity));
    recyclerViewOrders.setAdapter(orderAdapter);

    return view;
}

适配器:

package com.slavafleer.tipcalculator;

import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import java.util.ArrayList;

/**
 * Order Adapter for Order Recycler View
 */
public class OrderAdapter extends RecyclerView.Adapter<OrderHolder> {

    private Context context;
    private ArrayList<Order> orders;

    public OrderAdapter(Context context, ArrayList<Order> orders) {

        this.context = context;
        this.orders = orders;
    }

    @Override
    public OrderHolder onCreateViewHolder(ViewGroup parent, int viewType) {

        LayoutInflater layoutInflater = (LayoutInflater)
                context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

        View view = layoutInflater.inflate(R.layout.item_order, parent, false);

        return new OrderHolder(view);
    }

    // TODO: why it has been done just once ?
    @Override
    public void onBindViewHolder(OrderHolder holder, int position) {

        Order order = orders.get(position);

        holder.bindOrder(order);
    }

    @Override
    public int getItemCount() {
        return orders.size();
    }
}

持有人:

package com.slavafleer.tipcalculator;

import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.widget.TextView;

/**
 * Order Holder for Order Recycler View
 */
public class OrderHolder extends RecyclerView.ViewHolder {

    private TextView textViewOrderId;
    private TextView textViewDinerId;
    private TextView textViewPrice;

    public OrderHolder(View itemView) {
        super(itemView);

        textViewOrderId = (TextView) itemView.findViewById(R.id.textViewOrderId);
        textViewDinerId = (TextView) itemView.findViewById(R.id.textViewDinerId);
        textViewPrice = (TextView) itemView.findViewById(R.id.textViewPrice);
    }

    // Bind Data Object to the Views.
    public void bindOrder(Order order) {

        textViewOrderId.setText(order.getOrderId() + "");
        textViewDinerId.setText(order.getDinerId() + "");
        textViewPrice.setText(order.getPrice() + "");
    }


}
5个回答

12

首先,感谢Febi Mathew尝试帮助我解决这个问题。

我找到了解决方法。

我的Gradle中原始的一行代码是:

compile 'com.android.support:recyclerview-v7:23.2.0'

我仅为Recycler做了一个示例,结果相同,于是我尝试了一个较旧的版本

compile 'com.android.support:recyclerview-v7:23.1.1'

它完美地解决了问题。所以我想这不是我的错误=)。如果您知道如何报告此错误,请随时这样做。

更新: 问题在于我没有为我的项目设置wrap content的布局高度。出于我不理解的原因,在旧版本中这并不重要,但在新版本中,它会占据整个屏幕,而我没有想到尝试向下滑动它。


我不知道这是否重要,但我正在使用Android Studio 2.0 beta 6版本进行工作。 - Slava
可能是即时运行出了问题。你尝试过使用23.2库进行干净安装和构建吗? - WarrenFaith
WarrenFaith,我不太确定你的意思(您是否尝试使用23.2库进行干净安装和干净构建?)但这还没有结束=)在我的简单测试RecyclerView上,它像我之前说的那样工作,但在我的项目中它有旧效果。我想我会尝试卸载beta并在Android Studio的稳定版本上尝试相同的操作。 - Slava
我建议您从模拟器/设备中删除应用程序,执行“构建->清理”操作,然后再尝试使用23.2.0库运行和安装它。即时运行功能只是“注入”新代码,似乎仍存在一些问题,因此我想知道您的AS注入的代码是否已经有缺陷。 - WarrenFaith
4
我感觉很愚蠢 =) 问题出在我没有将我的项目的布局高度设置为自适应内容。原因是我不理解的,旧版本上这并不重要,但在新版本中它会占据整个屏幕,我没有想到尝试向下滑动。真是一个非常愚蠢的情况,但我很高兴它已经过去了。只是花了时间重新安装工作室 =)。再次感谢你的帮助。 - Slava
请在您的答案中更新评论中提到的布局高度发现。 - WarrenFaith

7
如果项目布局的最外层元素高度没有设置为“match_parent”值,而是设置为“wrap_content”或某个Ndp值,请检查它。例如:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout mlns:android="http://schemas.android.com/apk/res/android"
          xmlns:tools="http://schemas.android.com/tools"
          android:orientation="vertical"
          android:layout_width="match_parent"
          android:layout_height="wrap_content"  // Just like this!
    >
    <TextView
        android:id="@+id/item_title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
    />
</LinearLayout>

6

我也遇到了同样的问题,因为设置了错误的高度参数。

应该设置为wrap_content,但我将布局高度设置为match_parent。

因此,第一个列表项将占据列表视图中的所有空间,因此只显示一个列表项。


它对我帮助很大。我一直在研究为什么onBindViewHolder只调用了第一个项目而不是所有项目,即使我添加了日志。最终你的答案帮助了我。谢谢。 - scott

0

你能试试这个吗?

@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    LayoutInflater layoutInflater = (LayoutInflater)
            context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

    View view = layoutInflater.inflate(R.layout.item_order, parent, false);

    return new OrderHolder(view);
}

@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
    Order order = orders.get(position);

    OrderHolder orderHolder = (OrderHolder)holder;
    orderHolder.bindOrder(order);
}

onBindViewHolder 是 @Override,所以我无法更改它的参数。 - Slava
请用“extends RecyclerView.Adapter<RecyclerView.ViewHolder>”替换你的“extends RecyclerView.Adapter<OrderHolder>”。 - Febi M Felix
当OrderHolder继承自RecyclerView.ViewHolder时,为什么他需要替换它呢?在这种情况下没有必要这样做。 - WarrenFaith

0

我的上一个提交中,RecyclerView的支持版本为:24.2.1

后来我通过添加以下内容更新了build.gradle文件:

> configurations.all {
   >     resolutionStrategy.eachDependency { DependencyResolveDetails details ->
   >         def requested = details.requested
   >         if (requested.group == 'com.android.support') {
   >             if (!requested.name.startsWith("multidex")) {
   >                 details.useVersion '25.3.0'
   >             }
   >         }
   >     } }

所以在这之后,所有支持版本都已升级到25.3.0,除了“multidex”。这意味着recyclerview版本也已升级。

问题在于,在此之后运行构建时,我的recyclerview onbindviewholder方法没有被调用。

无论如何,我在注释上述代码并运行后找到了原因,能够使用我的recyclerview。

希望这对某人有用。

敬礼 Vinod


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,