【问题标题】:RecyclerView nested ViewHolder child viewsRecyclerView 嵌套 ViewHolder 子视图
【发布时间】:2015-10-01 16:28:07
【问题描述】:

当我尝试循环添加更多子视图到父视图时,我遇到了 RecyclerView 问题。当我滚动时,它会出现一秒钟的空白。是来自数据绑定还是视图渲染?

这是我的代码:

public class TournamentFixtureAdapter extends LoadMoreRecyclerViewAdapter<FixtureGroup> {
    private OnFixtureClickListener onFixtureClickListener = null;

    public TournamentFixtureAdapter(List<FixtureGroup> data) {
        super(data);
    }

    @Override
    protected RecyclerView.ViewHolder onCreateContentItemViewHolder(ViewGroup parent, int contentViewType) {
        return new TournamentFixtureHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item_tournament_fixture, parent, false));
    }

    @Override
    protected void onBindContentItemViewHolder(RecyclerView.ViewHolder holder, int position) {
        super.onBindContentItemViewHolder(holder, position);
        FixtureGroup fixtureGroup = data.get(position);
        ((TournamentFixtureHolder) holder).onFixtureClickListener = onFixtureClickListener;
        ((TournamentFixtureHolder) holder).parentPos = position;
        ((TournamentFixtureHolder) holder).binding.setFixtureGroup(fixtureGroup);
        ((TournamentFixtureHolder) holder).addFixtures(fixtureGroup.getFixtures());
    }

    public void setOnFixtureClickListener(OnFixtureClickListener onFixtureClickListener) {
        this.onFixtureClickListener = onFixtureClickListener;
    }

    static class TournamentFixtureHolder extends FixtureHolder {
        ListItemTournamentFixtureBinding binding = null;

        public TournamentFixtureHolder(View itemView) {
            super(itemView);
            binding = DataBindingUtil.bind(itemView);
        }
    }
}

public class FixtureHolder extends BaseAdapter.BaseHolder {
    LinearLayout           layoutMain             = null;
    OnFixtureClickListener onFixtureClickListener = null;
    int parentPos;

    public FixtureHolder(View itemView) {
        super(itemView);
        layoutMain = (LinearLayout) itemView.findViewById(R.id.layout_main);
        setIsRecyclable(layoutMain.getChildCount() > 0);
    }

    public void addFixtures(final ArrayList<Fixture> fixtures) {

        for (final Fixture fixture : fixtures) {
            LinearLayout parent = (LinearLayout) LayoutInflater.from(itemView.getContext()).inflate(R.layout.view_fixture, null);

            Utils.getDefaultClubLogo((NetworkImageViewPlus) parent.findViewById(R.id.netview_home_img)).setImageUrl(fixture.getHome().getImg(), AppController.getInstance().getImageLoader());
            Utils.getDefaultClubLogo((NetworkImageViewPlus) parent.findViewById(R.id.netview_away_img)).setImageUrl(fixture.getAway().getImg(), AppController.getInstance().getImageLoader());
            ViewFixtureBinding binding = DataBindingUtil.bind(parent);

            layoutMain.addView(parent);
            binding.setFixture(fixture);

            parent.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    onFixtureClickListener.onFixtureClick(parentPos, findFixturePosById(fixtures, fixture.getId()));
                }
            });
        }
    }

    private int findFixturePosById(ArrayList<Fixture> fixtures, int id) {
        for (int i = 0; i < fixtures.size(); i++) {
            if (fixtures.get(i).getId() == id) {
                return i;
            }
        }
        return 0;
    }
}

【问题讨论】:

  • 我假设您已将 LoadMoreRecyclerViewAdapter 扩展到 RecyclerView.Adapter ,为什么您不在 LoadMoreRecyclerViewAdapter 中执行所有这些操作
  • @L-X 我在该适配器中使用了两个视图。最后一项用于制作圆形指示器以加载更多数据,第二项用于正常视图。所以适配器中有两个视图持有者

标签: android android-recyclerview


【解决方案1】:

如果问题更多出在数据端(适配器),那么它可能会出现在正常布局上,而不仅仅是在滚动期间。例如,如果您从慢速服务器加载图像,则初始显示会很慢。由于它仅在您滚动时发生,这更多地表明布局管理器存在问题。

对于每个新视图,您必须从适配器中获取它,并将其添加到布局中。如果您在水平/垂直滚动中允许最大 dx,并且缓存了屏幕显示之外的回收视图,那么在布局管理器从适配器获取新视图并将其布局之前,内容可能会显示为空白。

因此有两个因素 - 水平和/或垂直 dx 太大、太快,以及回收(或废弃)视图的数量太少。因此,解决方案是减慢滚动速度,或者增加您在屏幕外添加的视图数量。

【讨论】:

  • 我认为增加浏览量可能有效。您能否提供它的示例代码。
  • 如果您正在编写自己的自定义布局管理器或扩展另一个 - 一旦调用滚动方法 (scrolledVerticallyBy, ScrollHorizo​​ntallyBy) - 那么您就可以控制 - 您知道 dx 是什么,所以他们是否看到空白取决于您是否在将用户偏移到新位置之前布置视图。只需确保在将用户偏移到该区域之前布局新视图,并且不应该有灰色空间。
  • 感谢您的帮助,但我设法解决了这个问题。也许这是一个小技巧,但它确实解决了问题。我通过返回必须在 onCreateContentItemViewHolder 生成的子视图的大小来覆盖 getContentItemViewType。再次感谢@Dennis Sheil
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-08-26
  • 2021-10-28
  • 2014-05-17
  • 2015-10-16
  • 1970-01-01
  • 1970-01-01
  • 2018-02-22
相关资源
最近更新 更多