NestedScrollView嵌套RecyclerView出现onBindViewHolder一直回调的问题

时间:2022-09-08 12:08:22

CoordinatorLayout中NestedScrollView嵌套RecyclerView出现onBindViewHolder的回调问题:
假设数据有860条,在初始化后显示一屏不滑动,onBindViewHolder 回调12次,
而嵌套了则在初始化后不滑动的情况下会回调860次,APP崩了。。。

2016年11月20日01:18:06补充

//设置 这个可以避免以上问题 但也意味着失去了本身设计用来提供支持WRAP_CONTENT的功能了
mRecyclerView.getLayoutManager().setAutoMeasureEnabled(false);

api要点:

1、This method is usually called by the LayoutManager with value true if it wants to support WRAP_CONTENT.

通常调用这个方法设置值为true的时候 就是用来支持WRAP_CONTENT功能的。。。

2、 True if the Layout should be measured by the RecyclerView, false if the LayoutManager wants to measure itself.

true 代表把布局交由recycleview测量 false 代表LayoutManager 自己测量

api 24.2.1

public void setAutoMeasureEnabled(boolean enabled)
Defines whether the layout should be measured by the RecyclerView or the LayoutManager wants to handle the layout measurements itself.
This method is usually called by the LayoutManager with value true if it wants to support WRAP_CONTENT. If you are using a public LayoutManager but want to customize the measurement logic, you can call this method with false and override LayoutManager.onMeasure(int, int) to implement your custom measurement logic.
AutoMeasure is a convenience mechanism for LayoutManagers to easily wrap their content or handle various specs provided by the RecyclerView's parent. It works by calling onLayoutChildren(RecyclerView.Recycler, RecyclerView.State) during an onMeasure(int, int) call, then calculating desired dimensions based on children's positions. It does this while supporting all existing animation capabilities of the RecyclerView.
AutoMeasure works as follows:
LayoutManager should call setAutoMeasureEnabled(true) to enable it. All of the framework LayoutManagers use auto-measure.
When onMeasure(int, int) is called, if the provided specs are exact, RecyclerView will only call LayoutManager's onMeasure and return without doing any layout calculation.
If one of the layout specs is not EXACT, the RecyclerView will start the layout process in onMeasure call. It will process all pending Adapter updates and decide whether to run a predictive layout or not. If it decides to do so, it will first call onLayoutChildren(RecyclerView.Recycler, RecyclerView.State) with RecyclerView.State.isPreLayout() set to true. At this stage, getWidth() and getHeight() will still return the width and height of the RecyclerView as of the last layout calculation.
After handling the predictive case, RecyclerView will call onLayoutChildren(RecyclerView.Recycler, RecyclerView.State) with RecyclerView.State.isMeasuring() set to true and RecyclerView.State.isPreLayout() set to false. The LayoutManager can access the measurement specs via getHeight(), getHeightMode(), getWidth() and getWidthMode().
After the layout calculation, RecyclerView sets the measured width & height by calculating the bounding box for the children (+ RecyclerView's padding). The LayoutManagers can override setMeasuredDimension(Rect, int, int) to choose different values. For instance, GridLayoutManager overrides this value to handle the case where if it is vertical and has 3 columns but only 2 items, it should still measure its width to fit 3 items, not 2.
Any following on measure call to the RecyclerView will run onLayoutChildren(RecyclerView.Recycler, RecyclerView.State) with RecyclerView.State.isMeasuring() set to true and RecyclerView.State.isPreLayout() set to false. RecyclerView will take care of which views are actually added / removed / moved / changed for animations so that the LayoutManager should not worry about them and handle each onLayoutChildren(RecyclerView.Recycler, RecyclerView.State) call as if it is the last one.
When measure is complete and RecyclerView's onLayout(boolean, int, int, int, int) method is called, RecyclerView checks whether it already did layout calculations during the measure pass and if so, it re-uses that information. It may still decide to call onLayoutChildren(RecyclerView.Recycler, RecyclerView.State) if the last measure spec was different from the final dimensions or adapter contents have changed between the measure call and the layout call.
Finally, animations are calculated and run as usual.
Parameters:
enabled - True if the Layout should be measured by the RecyclerView, false if the LayoutManager wants to measure itself.
See Also:
setMeasuredDimension(Rect, int, int), isAutoMeasureEnabled()