我正在尝试用recyclerview实现分页。我不知道为什么,但是只有当有结果响应时数据才会刷新,而没有结果它不会更新;筛选和排序工作正常,但位置选择不工作,因为它api为某些选择返回空列表。我在布局中也有swiperefreshlayout,当我再次使用swipe refresh刷新时,recyclerview更新之后。
这是我的分页侦听器和回收视图
public abstract class PaginationScrollListener extends RecyclerView.OnScrollListener {
LinearLayoutManager layoutManager;
public PaginationScrollListener(LinearLayoutManager layoutManager) {
this.layoutManager = layoutManager;
}
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
int visibleItemCount = layoutManager.getChildCount();
int totalItemCount = layoutManager.getItemCount();
int firstVisibleItemPosition = layoutManager.findFirstVisibleItemPosition();
if (!isLoading() && !isLastPage()) {
if ((visibleItemCount + firstVisibleItemPosition) >= totalItemCount
&& firstVisibleItemPosition >= 0
&& totalItemCount >= getTotalPageCount()) {
loadMoreItems();
}
}
}
protected abstract void loadMoreItems();
public abstract int getTotalPageCount();
public abstract boolean isLastPage();
public abstract boolean isLoading(); }
这是我的回收视图
GridLayoutManager gridLayoutManager = new GridLayoutManager(getmContext(), AppConstants.GRID_2);
mProductRecyclerView.setLayoutManager(gridLayoutManager);
mProductRecyclerView.setItemAnimator(new DefaultItemAnimator());
PaginationScrollListener paginationScrollListener = new PaginationScrollListener(gridLayoutManager) {
@Override
protected void loadMoreItems() {
isLoading = true;
//Increment page index to load the next one
CURRENT_PAGE += 1;
loadNextPage();
}
@Override
public int getTotalPageCount() {
return TOTAL_PAGE;
}
@Override
public boolean isLastPage() {
return isLastPage;
}
@Override
public boolean isLoading() {
return isLoading;
}
};
productListAdapter = new ProductListAdapter(getmContext(), R.layout.b_item_home_product);
productListAdapter.setiAdapterItemCheckChangeListener(this);
mProductRecyclerView.setAdapter(productListAdapter);
mProductRecyclerView.addOnScrollListener(paginationScrollListener);
itemClickDisposable = productListAdapter.getItemClickSubject().subscribe(productId -> {
UIHelper.getInstance().switchActivity(getmActivity(), ProductInfoActivity.class, UIHelper.ActivityAnimations.LEFT_TO_RIGHT, productId.toString(), AppConstants.K_ID, false);
});
viewModel.getProductsLiveData().observe(getViewLifecycleOwner(), responseList -> {
switch (responseList.status) {
case LOADING:
if (CURRENT_PAGE <= TOTAL_PAGE) {
showHideBottomProgress(true);
} else {
isLastPage = true;
}
if (isFirstPage) {
showMainLoading(true);
}
break;
case ERROR:
swipeRefreshLayout.setRefreshing(false);
if (CURRENT_PAGE <= TOTAL_PAGE) {
showHideBottomProgress(false);
}
if (isFirstPage) {
showMainLoading(false);
} else {
isLoading = false;
}
showErrorPrompt(responseList.message);
break;
case SUCCESS:
swipeRefreshLayout.setRefreshing(false);
if (CURRENT_PAGE <= TOTAL_PAGE) {
showHideBottomProgress(false);
}
if (isFirstPage) {
showMainLoading(false);
} else {
isLoading = false;
}
productListAdapter.addProducts(responseList.response);
break;
}
});
用于使用此方法加载页面和下一页
private void loadFirstPage() {
isFirstPage = true;
isLastPage = false;
resetProductsList();
viewModel.getProducts(getProductFilter());
}
private void loadNextPage() {
isFirstPage = false;
productFilter.setOffset(CURRENT_PAGE);
viewModel.getProducts(productFilter);
}
public void resetProductsList() {
productListAdapter.clear();
productFilter.setOffset(1);
}
这是我的适配器类
public class ProductListAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private static final int TYPE_SALE = 1, TYPE_POPULAR = 2, TYPE_LOADING = 3;
private Context mContext;
private int mResId;
private List<Product> products;
private PublishSubject<Integer> itemClickSubject = PublishSubject.create();
private IAdapterItemCheckChangeListener iAdapterItemCheckChangeListener;
private IAdapterItemClickListener iAdapterItemClickListener;
public ProductListAdapter(Context context, int resId, List<Product> data) {
mContext = context;
mResId = resId;
products = data;
}
public ProductListAdapter(Context context, int resId) {
mContext = context;
mResId = resId;
products = new ArrayList<>();
}
public List<Product> getProducts() {
return products;
}
public void addProducts(List<Product> newProducts) {
for (Product product : newProducts) {
addProduct(product);
}
}
public void addProduct(Product newProduct) {
products.add(newProduct);
notifyItemInserted(products.size() - 1);
}
public void setiAdapterItemCheckChangeListener(IAdapterItemCheckChangeListener iAdapterItemCheckChangeListener) {
this.iAdapterItemCheckChangeListener = iAdapterItemCheckChangeListener;
}
public void setiAdapterItemClickListener(IAdapterItemClickListener iAdapterItemClickListener) {
this.iAdapterItemClickListener = iAdapterItemClickListener;
}
public PublishSubject<Integer> getItemClickSubject() {
return itemClickSubject;
}
// Clean all elements of the recycler
public void clear() {
while (getItemCount() > 0) {
remove(getItem(0));
}
}
public void remove(Product product) {
int position = products.indexOf(product);
if (position > -1) {
products.remove(position);
notifyItemRemoved(position);
}
}
public Product getItem(int position) {
return products.get(position);
}
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
switch (viewType) {
case TYPE_SALE:
return new SaleHolder(LayoutInflater.from(mContext).inflate(R.layout.item_home_sale, parent, false));
case TYPE_LOADING:
return new ProgressItemHolder(LayoutInflater.from(mContext).inflate(R.layout.item_pagination, parent, false));
default:
return new ProductHolder(LayoutInflater.from(mContext).inflate(mResId, parent, false));
}
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position) {
if (getItemViewType(position) == TYPE_POPULAR) {
((ProductHolder) holder).setUpProductHolder(products.get(position));
} else if (getItemViewType(position) == TYPE_LOADING) {
} else {
((SaleHolder) holder).setupSaleHolder(products.get(position));
}
}
@Override
public int getItemViewType(int position) {
if (products.get(position).getType() == AppConstants.PRODUCT_TYPE.TYPE_SALE) {
return TYPE_SALE;
} else {
return TYPE_POPULAR;
}
}
@Override
public int getItemCount() {
return products.size();
}
@Override
public void onDetachedFromRecyclerView(@NonNull RecyclerView recyclerView) {
super.onDetachedFromRecyclerView(recyclerView);
itemClickSubject.onComplete();
}
public class SaleHolder extends RecyclerView.ViewHolder {
public SaleHolder(@NonNull View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
}
private void setupSaleHolder(Product product) {
}
}
public class ProgressItemHolder extends RecyclerView.ViewHolder {
@BindView(R.id.progress_wheel)
ProgressWheel progressWheel;
@BindView(R.id.tv_error)
TextView errorMsg;
public ProgressItemHolder(@NonNull View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
}
private void bindHolder(NetworkState networkState) {
if (networkState != null && networkState.getStatus() == NetworkState.Status.LOADING) {
progressWheel.setVisibility(View.VISIBLE);
progressWheel.spin();
} else {
progressWheel.setVisibility(View.GONE);
progressWheel.stopSpinning();
}
if (networkState != null && networkState.getStatus() == NetworkState.Status.FAILED) {
errorMsg.setVisibility(View.VISIBLE);
errorMsg.setText(R.string.please_connect_to_your_network);
} else {
errorMsg.setVisibility(View.GONE);
}
}
}
public class ProductHolder extends RecyclerView.ViewHolder implements CompoundButton.OnCheckedChangeListener, View.OnClickListener {
@BindView(R.id.iv_product_preview_image)
ImageView productImage;
@BindView(R.id.tv_product_name)
TextView productName;
@BindView(R.id.tv_product_price)
MagicText productPrice;
@BindView(R.id.tv_average_rating)
TextView productRating;
@BindView(R.id.cb_wishlist)
CheckBox wishlist;
@BindView(R.id.tv_product_quality)
TextView productQuality;
@BindView(R.id.tv_discount)
TextView discount;
@BindView(R.id.container_original_price)
ConstraintLayout originalPrice;
@BindView(R.id.tv_original_price)
TextView priceWithoutDiscount;
@BindView(R.id.tv_brand_name)
TextView brandName;
public ProductHolder(@NonNull View itemView) {
super(itemView);
ButterKnife.bind(this, itemView);
RxView.clicks(itemView)
.map(unit -> getAdapterPosition())
.subscribe(itemClickSubject);
wishlist.setOnCheckedChangeListener(this);
itemView.setOnClickListener(this);
}
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (iAdapterItemCheckChangeListener == null) return;
if (buttonView.isPressed()) {
iAdapterItemCheckChangeListener.onCheckChange(isChecked, getAdapterPosition());
}
}
public void setUpProductHolder(Product product) {
try {
productImage.setImageDrawable(null);
if (product.getBrandLabel() == null) {
brandName.setText("");
} else {
brandName.setText(product.getBrandLabel());
}
productName.setText(mContext.getString(R.string.product_full_name, product.getName()));
wishlist.setChecked(product.getWishList() >= 1);
// productPrice.setText(mContext.getString(R.string.price_with_currency, product.getPrice()));
float avgRating = product.getAverageRating() != null ? product.getAverageRating() : AppConstants.DEFAULT_RATING;
String ratingTrimed = String.format(Locale.getDefault(), "%.1f", avgRating);
productRating.setText(mContext.getString(R.string.average_rating, avgRating));
productQuality.setText(product.getQuality() != null ? product.getQuality() : "");
if (product.getDiscount() > 0) {
String fullPrice = mContext.getString(R.string.price_in_currency, product.getFinalPrice());
productPrice.change(fullPrice, mContext.getResources().getColor(R.color.colorBlack), 16, "normal", product.getFinalPrice());
discount.setVisibility(View.VISIBLE);
discount.setText(mContext.getString(R.string.discount_with_percent, product.getDiscount()));
originalPrice.setVisibility(View.VISIBLE);
priceWithoutDiscount.setText(product.getPrice());
} else {
String fullPrice = mContext.getString(R.string.price_in_currency, product.getPrice());
productPrice.change(fullPrice, mContext.getResources().getColor(R.color.colorBlack), 16, "normal", product.getPrice());
discount.setVisibility(View.GONE);
originalPrice.setVisibility(View.GONE);
}
if (product.getFree() > 0) {
String fullPrice = mContext.getString(R.string.price_in_currency, product.getSpecialPrice());
productPrice.change(fullPrice, mContext.getResources().getColor(R.color.colorBlack), 16, "normal", product.getSpecialPrice().toString());
originalPrice.setVisibility(View.VISIBLE);
priceWithoutDiscount.setText(product.getPrice());
discount.setVisibility(View.VISIBLE);
discount.setText(mContext.getString(R.string.discount_with_percent, AppConstants.DISCOUNT_100));
}
Glide.with(mContext).load(product.getImages().get(0).getValue()).apply(new RequestOptions()
.error(R.drawable.no_image_available)
.centerCrop().placeholder(R.drawable.no_image_available)).diskCacheStrategy(DiskCacheStrategy.RESOURCE).into(productImage);
} catch (Exception e) {
Log.d(getClass().getSimpleName(), "error");
}
}
@Override
public void onClick(View v) {
if (iAdapterItemClickListener == null) return;
iAdapterItemClickListener.onAdapterItemClick(v, getAdapterPosition());
}
}
}
这里我实现分页图像预览分页
编辑1:加载第一页时
{“discount”:false,“limit”:10,“offset”:1,“order”:“desc”,“sort”:“rating”}响应:加载第一页时
加载下一页时
{“城市”:“哈萨克斯坦”,“折扣”:假,“限制”:10,“偏移”:1,“顺序”:“描述”,“排序”:“评级”}
响应:当用其他过滤器再次加载页面时
2条答案
按热度按时间t9eec4r01#
我不太明白这个问题。可能是和线程有关的问题。
问题:分页屏幕是一个片段,位置微调器在工具栏中处于活动状态。我用的是
getActivity.findViewById()
获取微调器并填充片段本身中的数据。我为spinner设置了一个侦听器,所以每当单击项时,我都在调用片段中的api。我已经通过使用事件总线与片段通信解决了这个问题。现在我在活动本身中填充微调器。每当从该微调器单击项目时,我就触发事件;我在实现分页的片段中订阅了这个事件,因此调用了事件api。现在一切正常。
f5emj3cl2#
根据适配器类编码部分,您没有处理空列表。
在下面的方法中,您将逐个向适配器的产品列表添加产品。当列表为空时,循环将不工作,并且列表不会更改,因此值与以前的响应相同。
在方法中添加以下代码段