您如何处理要渲染的大量数据?

How do you process large amount of data to be render?

在下面的代码示例中,需要使用ListViewRecyclerView

加载5万个Customer
// current process, I am using pagination to load items
List<Customer> customers = mCustomerModule.get(limit, offset);
mAdapter.addItems(customer);
    

问题

  1. 滚动时速度慢,当达到大量客户时

问题

  1. 我的分页过程会降低性能吗?
  2. Couchbase lite 1.3 浏览量真的很慢吗?

目标

  1. 提高性能
  2. 更流畅地查看客户列表

您要查找的内容叫做Endless Scrolling。看看这篇描述问题并提出解决方案的文章:使用 ListView 和 RecyclerView:

Endless Scrolling with AdapterViews and RecyclerView

更新

以下是使用 RecyclerView 实现它的方法(信息取自上面 link)

按原样使用此代码,这将是 EndlessRecyclerViewScrollListener,它将对 RecyclerView 上的滚动做出反应。所以你需要将你的 RecyclerView 的 addOnScrollListener 设置为这个 class:

的一个实例
public abstract class EndlessRecyclerViewScrollListener extends RecyclerView.OnScrollListener {
// The minimum amount of items to have below your current scroll position
// before loading more.
private int visibleThreshold = 5;
// The current offset index of data you have loaded
private int currentPage = 0;
// The total number of items in the dataset after the last load
private int previousTotalItemCount = 0;
// True if we are still waiting for the last set of data to load.
private boolean loading = true;
// Sets the starting page index
private int startingPageIndex = 0;

RecyclerView.LayoutManager mLayoutManager;

public EndlessRecyclerViewScrollListener(LinearLayoutManager layoutManager) {
    this.mLayoutManager = layoutManager;
}

public EndlessRecyclerViewScrollListener(GridLayoutManager layoutManager) {
    this.mLayoutManager = layoutManager;
    visibleThreshold = visibleThreshold * layoutManager.getSpanCount();
}

public EndlessRecyclerViewScrollListener(StaggeredGridLayoutManager layoutManager) {
    this.mLayoutManager = layoutManager;
    visibleThreshold = visibleThreshold * layoutManager.getSpanCount();
}

public int getLastVisibleItem(int[] lastVisibleItemPositions) {
    int maxSize = 0;
    for (int i = 0; i < lastVisibleItemPositions.length; i++) {
        if (i == 0) {
            maxSize = lastVisibleItemPositions[i];
        }
        else if (lastVisibleItemPositions[i] > maxSize) {
            maxSize = lastVisibleItemPositions[i];
        }
    }
    return maxSize;
}

// This happens many times a second during a scroll, so be wary of the code you place here.
// We are given a few useful parameters to help us work out if we need to load some more data,
// but first we check if we are waiting for the previous load to finish.
@Override
public void onScrolled(RecyclerView view, int dx, int dy) {
    int lastVisibleItemPosition = 0;
    int totalItemCount = mLayoutManager.getItemCount();

    if (mLayoutManager instanceof StaggeredGridLayoutManager) {
        int[] lastVisibleItemPositions = ((StaggeredGridLayoutManager) mLayoutManager).findLastVisibleItemPositions(null);
        // get maximum element within the list
        lastVisibleItemPosition = getLastVisibleItem(lastVisibleItemPositions);
    } else if (mLayoutManager instanceof GridLayoutManager) {
        lastVisibleItemPosition = ((GridLayoutManager) mLayoutManager).findLastVisibleItemPosition();
    } else if (mLayoutManager instanceof LinearLayoutManager) {
        lastVisibleItemPosition = ((LinearLayoutManager) mLayoutManager).findLastVisibleItemPosition();
    } 

    // If the total item count is zero and the previous isn't, assume the
    // list is invalidated and should be reset back to initial state
    if (totalItemCount < previousTotalItemCount) {
        this.currentPage = this.startingPageIndex;
        this.previousTotalItemCount = totalItemCount;
        if (totalItemCount == 0) {
            this.loading = true;
        }
    }
    // If it’s still loading, we check to see if the dataset count has
    // changed, if so we conclude it has finished loading and update the current page
    // number and total item count.
    if (loading && (totalItemCount > previousTotalItemCount)) {
        loading = false;
        previousTotalItemCount = totalItemCount;
    }

    // If it isn’t currently loading, we check to see if we have breached
    // the visibleThreshold and need to reload more data.
    // If we do need to reload some more data, we execute onLoadMore to fetch the data.
    // threshold should reflect how many total columns there are too
    if (!loading && (lastVisibleItemPosition + visibleThreshold) > totalItemCount) {
        currentPage++;
        onLoadMore(currentPage, totalItemCount, view);
        loading = true;
    }
}

// Call this method whenever performing new searches
public void resetState() {
    this.currentPage = this.startingPageIndex;
    this.previousTotalItemCount = 0;
    this.loading = true;
}

// Defines the process for actually loading more data based on page
public abstract void onLoadMore(int page, int totalItemsCount, RecyclerView view);

}

在提到的 onLoadMore 方法中,通过发送网络请求或从另一个来源加载额外的项目到适配器中。

例如:

scrollListener = new EndlessRecyclerViewScrollListener(linearLayoutManager) {
       @Override
       public void onLoadMore(int page, int totalItemsCount, RecyclerView view) {
           // Triggered only when new data needs to be appended to the list
           // Add whatever code is needed to append new items to the bottom of the list
           loadNextDataFromApi(page);
       }
  };
  // Adds the scroll listener to RecyclerView
  rvItems.addOnScrollListener(scrollListener);

当您打算执行新搜索时,请确保从列表中清除现有内容并尽快通知适配器内容已更改。还要确保使用 resetState 方法重置 EndlessRecyclerViewScrollListener 的状态:

// 1. First, clear the array of data
listOfItems.clear();
// 2. Notify the adapter of the update
recyclerAdapterOfItems.notifyDataSetChanged(); // or      notifyItemRangeRemoved
// 3. Reset endless scroll listener when performing a new search
scrollListener.resetState();