大型项目的 RecyclerView

RecyclerView for large items

在我们的应用程序中,我们有一个 RecyclerView 在水平列表中显示大型项目。我们使用 LinearLayoutManager 来做到这一点。当用户滚动屏幕时会出现此问题。当下一个大项目需要出现在屏幕上时 UI 被冻结。

我们想要实现的是 RecyclerView 项的某种延迟加载。因此类似于 facebook 的实现用户看到一个存根,一旦他停止滚动 UI 将更新以显示实际内容。

问题是 - 正确的扩展点是什么?我应该实施自定义 LayoutManager 吗?或者有现成的解决方案吗?

没有看到你到底在做什么,我只能提出一个高水平的建议。该建议是将滚动侦听器附加到 recyclerView。

这对你有用吗?

        final int firstVisiblePosition = layoutManager.findFirstVisibleItemPosition();
    final int lastVisiblePosition = layoutManager.findLastVisibleItemPosition();

    myRecyclerView.setOnScrollListener(new RecyclerView.OnScrollListener() {
        @Override
        public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
            super.onScrolled(recyclerView, dx, dy);
        }

        @Override
        public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
            super.onScrollStateChanged(recyclerView, newState);

            switch (newState) {
                case RecyclerView.SCROLL_STATE_IDLE:
                    for (int i = firstVisiblePosition; i <= lastVisiblePosition; i++) {
                        // start content loading here
                        recyclerView.getChildAt(i).loadMyContent;
                    }
                    break;
                case RecyclerView.SCROLL_STATE_DRAGGING:
                    for (int i = firstVisiblePosition; i <= lastVisiblePosition; i++) {
                        // cancel content loading here
                        recyclerView.getChildAt(i).cancelLoad;
                    }
                    break;
                case RecyclerView.SCROLL_STATE_SETTLING:
                    // you could load content here, but it could end up off screen by the time it stops, so I would not recommend it
                    break;
            }
        }
    });

我想补充一点,如果您正在加载图像,请查看 Picasso library:

来自毕加索的网页:

适配器下载

自动检测适配器重复使用并取消先前的下载。

@Override public void getView(int position, View convertView, ViewGroup parent) {
  SquaredImageView view = (SquaredImageView) convertView;
  if (view == null) {
    view = new SquaredImageView(context);
  }
  String url = getItem(position);

  Picasso.with(context).load(url).into(view);
}

如果您使用 Xamarin 作为标签,请说您可以这样做:

public class  XamarinRecyclerViewOnScrollListener : RecyclerView.OnScrollListener
{
    public delegate void LoadMoreEventHandler(object sender, EventArgs e);
    public event LoadMoreEventHandler LoadMoreEvent;

    private LinearLayoutManager LayoutManager;

    public XamarinRecyclerViewOnScrollListener (LinearLayoutManager layoutManager)
    {
        LayoutManager = layoutManager;
    }

    public override void OnScrolled (RecyclerView recyclerView, int dx, int dy)
    {
        base.OnScrolled (recyclerView, dx, dy);

        var visibleItemCount = recyclerView.ChildCount;
        var totalItemCount = recyclerView.GetAdapter().ItemCount;
        var pastVisiblesItems = LayoutManager.FindFirstVisibleItemPosition();

        if ((visibleItemCount + pastVisiblesItems) >= totalItemCount) {
            LoadMoreEvent (this, null);
        }
    }
}

要在您的视图中使用它,请使用:

public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
    {
        var view = base.OnCreateView(inflater, container, savedInstanceState);

        var recyclerView = view.FindViewById<RecyclerView>(Resource.Id.my_recycler_view);
        if (recyclerView != null)
        {
            recyclerView.HasFixedSize = true;

            var layoutManager = new LinearLayoutManager(Activity);

            var onScrollListener = new XamarinRecyclerViewOnScrollListener (layoutManager);
            onScrollListener.LoadMoreEvent += (object sender, EventArgs e) => {
                //Load more stuff here
            };

            recyclerView.AddOnScrollListener (onScrollListener);

            recyclerView.SetLayoutManager(layoutManager);
        }
        return view;
    }