0

我有一个片段,一旦加载,我就会在其中获取一些博客。我在这里进行分页,所以,我最初为 page=1 加载数据。

我还实现了一个 scrollListener ,它在用户向下滚动时进行后续 API 调用以加载更多博客。每次进行新调用时,我都会在recyclerview 的末尾添加一个progressBar。代码如下。

正在发生的问题是,我得到了多个进度对话框,如图所示多个进度对话框。此外,即使页码不断增加,它也会不断加载更多数据。不添加行号(1-4),就不会出现无穷数据的问题。我只是没有得到进度对话框。

我只是不明白代码的问题。每当进行新的 API 调用时,我只想在 recyclerview 的末尾添加progressdialog。

    BlogsRecyclerViewAdapter adapter;
    ArrayList<BlogResponse> blogsList;

// 片段中scrollListener的代码

    blogsList = new ArrayList<>();
    adapter = new BlogsRecyclerViewAdapter(getContext(), blogsList);
    blogsRecyclerView.setAdapter(adapter);
    final LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getContext());
    blogsRecyclerView.setLayoutManager(linearLayoutManager);

    scrollListener = new BlogsRecyclerViewScrollListener(linearLayoutManager) {
        @Override
        public boolean onLoadMore(final int page, int totalItemsCount, RecyclerView view) {

            blogsList.add(null);  //line-1
            adapter.notifyItemInserted(blogsList.size()-1); //line-2

            Handler handler = new Handler();
            handler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    //   remove progress item
                    blogsList.remove(blogsList.size() - 1); //line-3
                    adapter.notifyItemRemoved(blogsList.size()); //line-4
                    fetchBlogs(page);
                }
            }, 2000); //time 2 seconds
            return true; // ONLY if more data is actually being loaded; false otherwise.
        }
    };
    fetchBlogs(1);
   blogsRecyclerView.addOnScrollListener(scrollListener);

// BlogsRecyclerViewScrollListener

 public abstract class BlogsRecyclerViewScrollListener extends RecyclerView.OnScrollListener{
private int visibleThreshold = 3;

private int currentPage = 1;

private int previousTotalItemCount = 0;

private boolean loading = true;

private int startingPageIndex = 1;

RecyclerView.LayoutManager mLayoutManager;

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

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;
}

@Override
public void onScrolled(RecyclerView view, int dx, int dy) {
    int lastVisibleItemPosition = 0;
    int totalItemCount = mLayoutManager.getItemCount();

    lastVisibleItemPosition = ((LinearLayoutManager) mLayoutManager).findLastVisibleItemPosition();

    if (totalItemCount < previousTotalItemCount) {
        this.currentPage = this.startingPageIndex;
        this.previousTotalItemCount = totalItemCount;
        if (totalItemCount == 0) {
            this.loading = true;
        }
    }

    if (loading && (totalItemCount > previousTotalItemCount)) {
        loading = false;
        previousTotalItemCount = totalItemCount;
    }

    if (!loading && (lastVisibleItemPosition + visibleThreshold) >= totalItemCount) {
        currentPage++;
        onLoadMore(currentPage, totalItemCount, view);
        loading = true;
    }
}
    public void resetState() {
        this.currentPage = this.startingPageIndex;
        this.previousTotalItemCount = 0;
        this.loading = true;
    }

    public abstract boolean onLoadMore(int page, int totalItemsCount, 
    RecyclerView view);
}

// 获取博客方法

     private void fetchBlogs(final int page) {

        apiServiceWithoutVersion.getBlogs(String.valueOf(page))
        .enqueue(new 
        Callback<ArrayList<BlogResponse>>() {
        @Override
        public void onResponse(Call<ArrayList<BlogResponse>> call, 
        Response<ArrayList<BlogResponse>> response) {
            if(response.isSuccessful()){  
                for(BlogResponse blogResponse: response.body()){
                    blogsList.add(blogResponse);
                }
                adapter.notifyDataSetChanged();
            }else{
                //some code to show error
            }
        }

        @Override
        public void onFailure(Call<ArrayList<BlogResponse>> call, Throwable t) {
            //some code to show failure
        }
    });
}

// item_loading.xml

  <?xml version="1.0" encoding="utf-8"?>
  <LinearLayout 
     xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
     android:orientation="vertical">
    <ProgressBar
        android:id="@+id/progress_bar_at_bottom"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_horizontal" />
 </LinearLayout>

// BlogsRecyclerViewAdapter

public class BlogsRecyclerViewAdapter extends 
RecyclerView.Adapter<RecyclerView.ViewHolder> {

Context mContext;
ArrayList<BlogResponse> mObjects;
ArrayList<BlogResponse> mFilteredObjects;
onItemClickListener mListener;

private final int VIEW_ITEM = 1;
private final int VIEW_PROG = 0;

public void setOnItemClickListener(onItemClickListener listener){
    mListener = listener;
}

public BlogsRecyclerViewAdapter(Context context, ArrayList<BlogResponse> objects){
    mContext = context;
    mObjects = objects;
    mFilteredObjects = objects;
}

@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    RecyclerView.ViewHolder holder = null;
    if(viewType==VIEW_ITEM) {
        View view = View.inflate(mContext, R.layout.list_item_blogs_recycler_view, null);
        holder = new BlogViewHolder(view);
    }else{
        View v = LayoutInflater.from(parent.getContext())
                .inflate(R.layout.item_loading, parent, false);

        holder = new ProgressViewHolder(v);
    }
    return holder;
}

@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) {

    if(holder instanceof BlogViewHolder){
        //code for blogs

        holder.itemView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mListener.onItemClick(position);
            }
        });
    }else{
        ((ProgressViewHolder)holder).progressBar.setIndeterminate(true);
    }

}

@Override
public int getItemCount() {
    return mFilteredObjects.size();
}

private class BlogViewHolder extends RecyclerView.ViewHolder {

    public BlogViewHolder(View itemView) {
        super(itemView);
        // Code for blogs
    }
}

private class ProgressViewHolder extends RecyclerView.ViewHolder {
    public ProgressBar progressBar;
    public ProgressViewHolder(View v) {
        super(v);
        progressBar = v.findViewById(R.id.progress_bar_at_bottom);
    }
}

public interface onItemClickListener{
    void onItemClick(int position);
}


@Override
public int getItemViewType(int position) {
    return mObjects.get(position)!=null? VIEW_ITEM: VIEW_PROG;
}

}

4

3 回答 3

1

您可以尝试检查数据当前是否正在加载

if(blogsList.get(blogsList.size() - 1) != null) {
    blogsList.add(null);  //line-1
    adapter.notifyItemInserted(blogsList.size()-1); //line-2

    Handler handler = new Handler();
    handler.postDelayed(new Runnable() {
        @Override
        public void run() {
            //   remove progress item
            blogsList.remove(blogsList.size() - 1); //line-3
            adapter.notifyItemRemoved(blogsList.size()); //line-4
            fetchBlogs(page);
        }
    }, 2000); //time 2 seconds
}
于 2018-04-12T13:20:25.983 回答
0

在您的情况下,有些商品onLoadMore()在收到您的回复之前已多次调用。因此,它会添加null到您的列表中,以便您在列表中显示多个progressBar

因此,您必须在滚动更多之后进行调试。

于 2018-04-12T12:55:17.593 回答
0
// The minimum number of items to have below your current scroll position
// before loading more.
private int visibleThreshold = 0;

visibleThreshold根据列表项视图高度更改或调整它。您可以查看链接以获取更多详细信息。这将帮助您停止滚动时的多个 API 调用。

于 2018-04-13T13:04:12.867 回答