滚动时将更多数据加载到recycleview

Posted

技术标签:

【中文标题】滚动时将更多数据加载到recycleview【英文标题】:load more data into recycleview while scrolling 【发布时间】:2019-12-25 18:18:17 【问题描述】:

首先我从服务器读取数据并将其放入ArrayList。接下来,我将ArrayList 放入Adapter 中以获得RecyclerView。当用户到达终点时,我想向服务器发送请求并获取RecyclerView 的数据。现在,我做到了,而且效果很好。但是,当我添加更多数据时,我的 RecyclerView 移动到第一项,我必须向下滚动才能看到新数据...我想在 RecyclerView 的底部添加更多数据而不返回顶部.

这是我向服务器发送请求并填写我的ArrayList的方法:

private void getPosts(final Integer page, Integer limit) 
    getPosts(null, page, limit, new RemoteCallback<ResponseBody>() 
        @Override
        public void onSuccess(ResponseBody responseBody) 

            try 
                JSONArray data = new JSONArray(responseBody.string());
                if (data.length() == 0) 
                    Toast.makeText(getApplicationContext(), "Finish", Toast.LENGTH_LONG).show();
                 else 
                    for (int i = 0; i < data.length(); i++) 
                        posts = getPosts_(data);
                    
                
             catch (Exception e) 
            
            posts2.addAll(posts);
        

        @Override
        public void onUnauthorized() 
            Log.e("data", "onUnauthorized");
        

        @Override
        public void onFailed(Throwable throwable) 
            Log.e("data", "onFailed");
        
    );

这是我的Activity

public class MainActivity2 extends AppCompatActivity 
    private static int ITEM_REQUEST_INITIAL_OFFSET = 1;
    private static final int ITEM_REQUEST_LIMIT = 10;
    private APIService mAPIService;
    ProgressBar progressBar;
    RecyclerView recyclerView;
    AdapterContent item2RecyclerAdapter;
    private int mLoadedItems = 0;
    public static List<Post> posts = new ArrayList<Post>();
    List<Post> posts2 = new ArrayList<Post>();

    @Override
    protected void onCreate(Bundle savedInstanceState) 
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main2);

        mAPIService = ApiUtils.getAPIService();
        progressBar = findViewById(R.id.item_progress_bar);
        recyclerView = findViewById(R.id.recycler_view);
        getPosts(ITEM_REQUEST_INITIAL_OFFSET, ITEM_REQUEST_LIMIT);

        LinearLayoutManager linearLayoutManager = new LinearLayoutManager(MainActivity2.this);
        linearLayoutManager.setOrientation(LinearLayoutManager.VERTICAL);
        recyclerView.setLayoutManager(linearLayoutManager);
        recyclerView.addItemDecoration(new DividerItemDecoration(MainActivity2.this, DividerItemDecoration.VERTICAL));
recyclerView.setAdapter(adapter) item2RecyclerAdapter = new AdapterContent(posts2);
        recyclerView.addOnScrollListener(new EndlessRecyclerOnScrollListener() 
            @Override
            public void onLoadMore() 
                new Handler().postDelayed(new Runnable() 
                    @Override
                    public void run() 
                        getPosts(ITEM_REQUEST_INITIAL_OFFSET, 10);
                    
                , 1500);
                ITEM_REQUEST_INITIAL_OFFSET++;
            
        );
    

这是我的Adapter 内容:

public class AdapterContent extends RecyclerView.Adapter<AdapterContent.SecondCollectionViewHolder> 
    private List<Post> posts;
    private Context context;
    private RemoteCallback<ResponseBody>remoteCallback;
    public SharedPreferences sp;
    public boolean state;


    public AdapterContent(List<Post> postList) 
        this.context = context;
        this.posts = postList;
        this.remoteCallback= remoteCallback;
    

    @Override
    public AdapterContent.SecondCollectionViewHolder onCreateViewHolder(ViewGroup parent, int viewType) 
        View secondCollectionView = LayoutInflater.from(parent.getContext()).inflate(R.layout.row, parent, false);
        return new SecondCollectionViewHolder(secondCollectionView);
    

    @Override
    public long getItemId(int position) 
        return super.getItemId(position);
    

    @Override
    public void onBindViewHolder(final AdapterContent.SecondCollectionViewHolder secondHolder, final int position) 
        final Post post = posts.get(position);

        secondHolder.txt_postTitle.setText(post.getTitle());
        Log.i("mhs",post.getTitle());
    
    public void add(Post r) 
        circleList.add(r);
        notifyItemInserted(posts.size() - 1);
    

    public void addAll(ArrayList<Post> moveResults) 
        for (Post result : moveResults) 
            add(result);
        
    

    @Override
    public int getItemCount() 
        return posts.size();
    

    public class SecondCollectionViewHolder extends RecyclerView.ViewHolder 

        public TextView txt_postTitle;
        public RelativeLayout relativeLayout;

        public SecondCollectionViewHolder(View itemView) 
            super(itemView);

            txt_postTitle = (TextView) itemView.findViewById(R.id.txt_postTitle);    
        
    

我的问题是如何在不转到RecyclerView 的第一行的情况下添加数据?

【问题讨论】:

【参考方案1】:

当在列表末尾收到更多加载时,使用自定义库或帮助程序延迟加载实现

abstract class EndlessListener(private val carouselLayoutManager: CarouselLayoutManager) :
    RecyclerView.OnScrollListener() 

    private val visibleThreshold = 5
    private var currentPage = 0
    private var previousTotalItemCount = 0
    private var loading = true
    private var startingPageIndex = 0

    fun getLastVisibleItem(lastVisibleItemPositions: IntArray): Int 
        var maxSize = 0
        for (i in lastVisibleItemPositions.indices) 
            if (i == 0) 
                maxSize = lastVisibleItemPositions[i]
             else if (lastVisibleItemPositions[i] > maxSize) 
                maxSize = lastVisibleItemPositions[i]
            
        
        return maxSize
    

    override fun onScrolled(view: RecyclerView, dx: Int, dy: Int) 
        val lastVisibleItemPosition = (carouselLayoutManager as LinearLayoutManager).findLastVisibleItemPosition()
        val totalItemCount = carouselLayoutManager.itemCount

        if (totalItemCount < previousTotalItemCount) 
            currentPage = startingPageIndex
            previousTotalItemCount = totalItemCount
            if (totalItemCount == 0) 
                loading = true
            
        

        if (loading && totalItemCount > previousTotalItemCount) 
            loading = false
            previousTotalItemCount = totalItemCount
        

        if (!loading && lastVisibleItemPosition + visibleThreshold > totalItemCount) 
            currentPage++
            onLoadMore(currentPage, totalItemCount, view)
            loading = true
        
    

    fun resetState() 
        this.currentPage = this.startingPageIndex
        this.previousTotalItemCount = 0
        this.loading = true
    

    abstract fun onLoadMore(page: Int, totalItemsCount: Int, view: RecyclerView)


并添加一个监听器来改变滚动位置

 recycelerView.addOnScrollListener(object : EndlessListener(layoutManager) 
                override fun onLoadMore(page: Int, totalItemsCount: Int, view: RecyclerView) 

                
            )

【讨论】:

以上是关于滚动时将更多数据加载到recycleview的主要内容,如果未能解决你的问题,请参考以下文章

向下滚动以使用 recycleview 和 SwipeRefreshLayout 加载数据

下拉加载更多内容(滚动加载)

滚动时将新项目添加到列表时出现数组索引超出范围异常

自定义加载更多的Recycleview

Swift,将更多数据加载到表视图中会导致滚动滞后

如何从post async http请求下载数据时将数据加载到reclyerview中