简体   繁体   English

RecyclerView getChildCount() 和 getItemCount() 返回相同的值

[英]RecyclerView getChildCount() and getItemCount() returns same value

RecyclerView has an InfiniteScrollListener and inside that listener, in OnScrolled() method I calculate visible and total item count to check if new items should be loaded. RecyclerView有一个 InfiniteScrollListener 并且在该侦听器内部,在OnScrolled()方法中,我计算可见和总项目数以检查是否应加载新项目。 When totalItemCount and visibleItemCount are the same, it causes an infinite loop of loading.当 totalItemCount 和 visibleItemCount 相同时,会导致加载无限循环。 The listener works flawlessly with my other RecyclerView s which does NOT have CoordinatorLayout or NestedScrollView as a parent.侦听器与我其他没有CoordinatorLayoutNestedScrollView作为父项的RecyclerView完美配合。 I want to keep this structure because the customer won't accept a change.我想保留这种结构,因为客户不会接受更改。

I've got a fragment inside an activity that has a layout like this我在一个具有这样布局的活动中有一个片段

CoordinatorLayout{
 NestedScrollView{
    RecyclerView{
    }
 }
}

sdk versions sdk 版本

compileSdkVersion 24
buildToolsVersion "23.0.3"
...
minSdkVersion 21
targetSdkVersion 24

fragment_profile.xml as parent layout fragment_profile.xml 作为父布局

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout 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="match_parent">

    <android.support.design.widget.AppBarLayout
        android:id="@+id/app_bar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/AppTheme.AppBarOverlay"
        app:layout_behavior="com.paxotic.paxira.util.behavior.AppBarFlingBehavior">

        <android.support.design.widget.CollapsingToolbarLayout
            android:id="@+id/toolbar_layout"
            android:layout_width="match_parent"
            android:layout_height="@dimen/app_bar_height_small"
            app:contentScrim="?attr/colorPrimary"
            app:layout_scrollFlags="scroll|exitUntilCollapsed">

            <RelativeLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:background="#000000"
                app:layout_collapseMode="parallax">

                <ImageView
                    android:id="@+id/img_background"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:alpha="0.5"
                    android:scaleType="centerCrop"
                    tools:src="@drawable/bg_greeting_activity" />

            </RelativeLayout>

        </android.support.design.widget.CollapsingToolbarLayout>

    </android.support.design.widget.AppBarLayout>

    <include
        layout="@layout/activity_profile_content"
        app:layout_behavior="@string/appbar_scrolling_view_behavior" />

    <android.support.design.widget.FloatingActionButton
       ... />

</android.support.design.widget.CoordinatorLayout>

fragment_profile.xml as child layout fragment_profile.xml 作为子布局

<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.NestedScrollView 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="match_parent"
    app:layout_behavior="@string/appbar_scrolling_view_behavior">

    ...

    <android.support.v7.widget.RecyclerView
        android:id="@+id/feedRecycler"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:clipToPadding="false"
        android:paddingBottom="@dimen/spacing_normal"
        tools:listitem="@layout/list_item_activity" />

    ...

</android.support.v4.widget.NestedScrollView>

ProfileFragment.java: relative function ProfileFragment.java:相对函数

private void init() {

    feedAdapter = new FeedAdapter(host);
    feedAdapter.setHasStableIds(true);

    LinearLayoutManager layoutManager = new LinearLayoutManager(host);
    feedRecycler.setLayoutManager(layoutManager);
    feedRecycler.setNestedScrollingEnabled(false);
    feedRecycler.setHasFixedSize(true);
    feedRecycler.setAdapter(feedAdapter);

    infiniteScrollListener = new InfiniteScrollListener(host, layoutManager) {
        @Override
        public void onLoadMore(int pageIndex) {
            if (!feedAdapter.isLoading) {
                loadFeed(pageIndex);
            }
        }
    };
    feedRecycler.addOnScrollListener(infiniteScrollListener);
}

InfiniteScrollListener.java无限滚动监听器.java

public abstract class InfiniteScrollListener extends RecyclerView.OnScrollListener {
    private int previousTotal = 0; // The total number of items in the dataset after the last load
    private boolean loading = false; // True if we are still waiting for the last set of data to load.
    private static final int VISIBLE_THRESHOLD = 5; // The minimum amount of items to have below your current scroll position before loading more.
    int firstVisibleItem, visibleItemCount, totalItemCount;

    private int current_page = 0;
    private int loadingItemCount;

    private LinearLayoutManager mLinearLayoutManager;

    public InfiniteScrollListener(Context context, LinearLayoutManager linearLayoutManager) {
        this.mLinearLayoutManager = linearLayoutManager;
        loadingItemCount = context.getResources().getInteger(R.integer.feed_pull_item_count);
    }

    @Override
    public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
        super.onScrolled(recyclerView, dx, dy);

        if (dy < 0) return;        // check for scroll down

        visibleItemCount = mLinearLayoutManager.getChildCount();
        totalItemCount = mLinearLayoutManager.getItemCount();
        firstVisibleItem = mLinearLayoutManager.findFirstVisibleItemPosition();

        synchronized (this) {

            if (!loading && (totalItemCount - visibleItemCount) <= (firstVisibleItem + VISIBLE_THRESHOLD)) {
                // End has been reached, Do something
                current_page++;
                onLoadMore(current_page);
                loading = true;
            }
        }
    }

    public abstract void onLoadMore(int current_page);

    public void setLoading(boolean loading) {
        this.loading = loading;
    }

    @Override
    public void onScrollStateChanged(RecyclerView view, int scrollState) {
        // Don't take any action on changed
    }
}

you are getting the same values from getChildCount() getItemCount() , because the recyclerview will returns the total number of items/child.您从getChildCount() getItemCount()获得相同的值,因为 recyclerview 将返回项目/子项的总数。

you must override one of the method, as per your usage, to get the value you want.您必须根据您的使用情况覆盖其中一种方法才能获得所需的值。 Do this in your custom recyclerview adapter.在您的自定义 recyclerview 适配器中执行此操作。

To do this, add this to your recyclerview adapter:为此,请将其添加到您的 recyclerview 适配器中:

@Overide
public int getChildCount() {
//return your desired value here after obtaining it
}

You get the real count of views.您可以获得实际的观看次数。 If adapter has 15 items and ((LinearLayoutManager) myRecyclerView.getLayoutManager()).getChildCount() returns you 7, there is two items visible in view due to max height or static height value after you update new item its till persists same height.如果适配器有 15 个项目,并且 ((LinearLayoutManager) myRecyclerView.getLayoutManager()).getChildCount() 返回 7,则在更新新项目后,由于最大高度或静态高度值,视图中有两个项目可见,直到保持相同的高度。

The count of items in the model (adapter) and the count of views are not the same thing.模型(适配器)中的项目数和视图数不是一回事。

RecyclerView doesn't hold views for all 15 items in memory, it only has 7 in your case. When you scroll, it reuses those 7 views for displaying different items. The purpose of this is improving the rendering performance.

If you want to get 15, then you should use mAdapter.getItemCount() instead.如果你想得到 15,那么你应该使用 mAdapter.getItemCount() 代替。

You shouldn't use recyclerView vertical in nestedScrollview .您不应该在nestedScrollview使用recyclerView垂直。 For finding wich item to show on RecyclerView and start getting a new item you can use your adapter.为了找到要在 RecyclerView 上显示的项目并开始获取新项目,您可以使用您的适配器。 In the RecyclerView.Adapter<> you can override onViewAttachedToWindow() :RecyclerView.Adapter<>您可以覆盖onViewAttachedToWindow()

@Override
public void onViewAttachedToWindow(@NonNull RecyclerView.ViewHolder holder) {
    super.onViewAttachedToWindow(holder);
    if ((getItemCount() - 1) == holder.getAdapterPosition()){
        Log.d(TAG,"list done");
        onLoadMore(current_page);
    } else {
        Log.d(TAG,"remain item : " + (getItemCount() - holder.getAdapterPosition() - 1));
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM