RecyclerView.onBindViewHolder只调用一次

时间:2016-04-25 12:04:13

标签: android dependencies android-recyclerview android-studio-2.0

经过数小时的研究,我终于在咨询官方帮助。

我有一个完美的RecyclerView.Adapter和RecyclerView.ViewHolders。但由于某些原因我不明白,RecyclerView.Adapter.onBindViewHolder未正确调用。

    private class AttendeeAdapter extends RecyclerView.Adapter<AttendeeHolder> {
    /*FIELDS*/
    private List<Attendee> mAttendeeList;

    /*CONSTRUCTORS*/
    public AttendeeAdapter(List<Attendee> attendees) {
        mAttendeeList = attendees;
        //Log.i(TAG, "AttendeeAdapter size: " + getItemCount());
    }

根据Log消息(项目计数作为预期列表的大小),我假设AttendeeAdapter已正确实例化。

所以我希望onBindViewHolder(VH,int)方法的调用次数与List的大小相同,但事实并非如此。该方法仅被称为ONCE!

    /*METHODS*/
    @Override
    public AttendeeHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        LayoutInflater layoutInflater = LayoutInflater.from(getActivity());
        View itemView = layoutInflater.inflate(R.layout.list_attendee, parent, false);
        return new AttendeeHolder(itemView);
    }

    @Override
    public void onBindViewHolder(AttendeeHolder holder, int position) {
        Attendee attendee = mAttendeeList.get(position);
        holder.bindAttendee(attendee, position);

        Log.i(TAG, "Binding ViewHolder #" + position);
        /* Binding ViewHolder #0 and that's it */
    }

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

我的AttendeeHolder(扩展RecyclerView.ViewHolder)如下:

    private class AttendeeHolder extends RecyclerView.ViewHolder {
    /*FIELDS*/
    private EditText mAttendeeNameEditText;
    private Attendee mAttendee;

    /*CONSTRUCTOR*/
    public AttendeeHolder(View itemView) {
        super(itemView);
        mAttendeeNameEditText = (EditText) itemView.findViewById(R.id.edit_text_list_item);
        mAmountEditTextList = new ArrayList<>(eventMaxCount);
      }

    /*METHODS*/
    public void bindAttendee(Attendee attendee, final int position) {
        mAttendee = attendee;
        String attendeeName = mAttendee.getName();

        // Set the name to the EditText if a name has already been set
        if (attendeeName != null) {
            mAttendeeNameEditText.setText(attendeeName);
        }
    }
}

并在主代码中实现为

List<Attendee> attendees = AttendeeLab.get().getAttendeeList();
     mAttendeeAdapter = new AttendeeAdapter(attendees);
     mAmountRecyclerView.setAdapter(mAttendeeAdapter);

我想代码可以工作(我想我没有做任何改动)但是gradle依赖关系可能没有正确设置。那是我尝试将recyclerview-v7:23.3.0修改为recyclerview-v7:23.1.0或其他任何东西(它们都没有工作)。

dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:23.3.0'
compile 'com.android.support:design:23.3.0'
compile 'com.android.support:support-v4:23.3.0'
compile 'com.android.support:recyclerview-v7:23.1.2'
}

任何帮助或评论将不胜感激。我希望从现在开始几个小时后,我会告诉你头疼的事。

7 个答案:

答案 0 :(得分:87)

问题不在您的代码中。确保将layout_height设置为RecyclerView子项的wrap_content

答案 1 :(得分:6)

处理RecyclerView周期中的onBindViewHolder行为。 RecyclerView.ViewHolder位置0 itemView

android:layout_height="match_parent"

占用当前显示的屏幕。应该触发Scroll和onBindViewHolder,但要确保getItemCount设置得恰当。

解决方案:

android:layout_height="wrap_content"

将ConstraintLayout解析为膨胀的itemView:

<?xml version="1.0" encoding="utf-8"?>    
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"><!-- IMPORTANT -->
    <!-- ... -->
</android.support.constraint.ConstraintLayout>

答案 2 :(得分:1)

对所有支持库使用相同的版本:

dependencies {

compile fileTree(dir: 'libs', include: ['*.jar'])

testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:23.3.0'
compile 'com.android.support:design:23.3.0'
compile 'com.android.support:support-v4:23.3.0'
compile 'com.android.support:recyclerview-v7:23.3.0' //<<< here
}

此外,RecyclerView应该添加'com.android.support:design:23.3.0'包 - 覆盖classor或者在构建过程中使用此“重复”包执行的任何魔法Gradle可能导致你的问题。

答案 3 :(得分:1)

对于最近才有此问题并正在运行beta版本的支持库的SDK 28的人,请将目标SDK更改为27,并使用27.1.1版本的支持库(在撰写本文时为最新版本)。

我在28.0.0-alpha3库中遇到了这个问题,在我的app.gradle中将版本更改为27.1.1,问题得以解决。

implementation 'com.android.support:appcompat-v7:27.1.1'
implementation 'com.android.support:design:27.1.1'
implementation 'com.android.support:support-vector-drawable:27.1.1'
implementation 'com.android.support:recyclerview-v7:27.1.1'

答案 4 :(得分:0)

还要检查是否将RecyclerView本身的高度设置为android:layout_height="wrap_content"android:layout_height="match_parent"。在这两种情况下,它都将适应单个项目的高度,并且看起来只是一个,但实际上您可以滚动列表。而是手动设置RecyclerView的高度。

答案 5 :(得分:0)

在我遇到的情况下,是当recyclerview只能水平滚动而不是垂直滚动时。

答案 6 :(得分:0)

在我的例子中,recyclerview 的单项布局的根布局(约束布局)高度设置为 ma​​tch_parent 而不是 'wrap_content',将其更改为 'wrap_content' 和问题已修复

<androidx.constraintlayout.widget.ConstraintLayout 
android:layout_width="match_parent"
android:layout_height="wrap_content">

<androidx.cardview.widget.CardView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    tools:ignore="MissingConstraints">

    <TextView
        android:id="@+id/tv_city_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="8dp"
        android:gravity="center"
        android:text="@{location.name}"
        android:textAppearance="@style/TextAppearance.AppCompat.Medium"
        android:typeface="serif" />

</androidx.cardview.widget.CardView>