我有一个 RecyclerView
具有动态的瓷砖数量。数据从服务器加载并显示在这些磁贴中。滑动用于将图像加载到这些瓦片上的化身中。问题是,每当我刷新列表或向其中添加更多项目时,它有时会为磁贴加载错误的图像。
例如,磁贴1上的一个用户将具有空白的化身,下一磁贴上的相同用户将具有不同的化身(另一用户的)。如果我刷新列表,它可能会变得正确,甚至更混乱(某个用户的第三个随机化身出现)。
我在工作中做错了什么 Adapter
? 下面是共享代码。
public class BookingAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder>
{
private final Context context;
private final Util util;
private final List<Booking> bookings;
private static final int TYPE_BOOKING = 0;
private static final int TYPE_LOADING = 1;
private OnLoadMoreListener loadMoreListener;
private boolean isMoreDataAvailable = true, isLoading = false;
public BookingAdapter(Context context, List<Booking> bookings)
{
this.context = context;
this.bookings = bookings;
util = new Util();
}
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType)
{
if(viewType == TYPE_BOOKING)
{
return new BookingViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.listitem_booking, parent, false));
}
else
{
return new LoadingViewHolder(LayoutInflater.from(parent.getContext()).inflate(R.layout.listitem_load, parent, false));
}
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder holder, int position)
{
if (position >= getItemCount() - 1 && isMoreDataAvailable && !isLoading && loadMoreListener != null)
{
isLoading = true;
loadMoreListener.onLoadMore();
}
if (getItemViewType(position) == TYPE_BOOKING)
{
((BookingViewHolder) holder).bindData(bookings.get(position));
}
}
@Override
public long getItemId(int position)
{
return position;
}
@Override
public int getItemViewType(int position)
{
if (bookings.get(position).getCreatedAt().equalsIgnoreCase("loading"))
{
return TYPE_LOADING;
}
else
{
return TYPE_BOOKING;
}
}
@Override
public int getItemCount()
{
return bookings != null ? bookings.size() : 0;
}
public class BookingViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener
{
private final CircularImageView avatar;
private final ImageView paymentStatusIcon;
private final TextView name;
private final TextView charges;
private final TextView timeSlot;
private final TextView status;
private final TextView cancel;
private final TextView dayOfWeek;
private final TextView dayOfMonth;
private final TextView month;
private Booking currentBooking = null;
private Appointment activeAppointment = null;
public BookingViewHolder(@NonNull View itemView)
{
super(itemView);
avatar = itemView.findViewById(R.id.avatar);
paymentStatusIcon = itemView.findViewById(R.id.paymentStatusIcon);
name = itemView.findViewById(R.id.name);
charges = itemView.findViewById(R.id.charges);
timeSlot = itemView.findViewById(R.id.timeslot);
status = itemView.findViewById(R.id.type);
cancel = itemView.findViewById(R.id.cancel);
dayOfWeek = itemView.findViewById(R.id.dayOfWeek);
dayOfMonth = itemView.findViewById(R.id.dayOfMonth);
month = itemView.findViewById(R.id.month);
cancel.setOnClickListener(this);
itemView.setOnClickListener(this);
}
void bindData(Booking booking)
{
this.currentBooking = booking;
String statusBooking = currentBooking.getStatus();
switch (statusBooking)
{
case Constants.JOB_STATUS_VISIT_PENDING:
case Constants.JOB_STATUS_CANCELLED:
case Constants.JOB_STATUS_OFFER_PENDING:
case Constants.JOB_STATUS_PENDING_CLIENT_APPROVAL:
this.activeAppointment = booking.getVisitAppointment();
break;
case Constants.JOB_STATUS_SCHEDULED:
case Constants.JOB_STATUS_IN_PROGRESS:
case Constants.JOB_STATUS_COMPLETED:
this.activeAppointment = booking.getServiceAppointment();
break;
default:
this.activeAppointment = new Appointment();
break;
}
if(activeAppointment.getAppointmentType().equalsIgnoreCase(Constants.APPOINTMENT_TYPE_SERVICE) && activeAppointment.getStatus().equalsIgnoreCase(Constants.JOB_STATUS_COMPLETED))
{
paymentStatusIcon.setVisibility(View.VISIBLE);
if(activeAppointment.getPaymentStatus().equalsIgnoreCase(Constants.PAYMENT_STATUS_PAID))
{
paymentStatusIcon.setImageDrawable(ContextCompat.getDrawable(context, R.drawable.vector_cash_check));
}
else if(activeAppointment.getPaymentStatus().equalsIgnoreCase(Constants.PAYMENT_STATUS_DECLINED))
{
paymentStatusIcon.setImageDrawable(ContextCompat.getDrawable(context, R.drawable.vector_cash_remove));
}
else
{
paymentStatusIcon.setImageDrawable(ContextCompat.getDrawable(context, R.drawable.vector_cash));
paymentStatusIcon.setImageTintList(ColorStateList.valueOf(ContextCompat.getColor(context, R.color.quantum_amber800)));
}
}
else
{
paymentStatusIcon.setVisibility(View.GONE);
}
if (statusBooking.equalsIgnoreCase(Constants.JOB_STATUS_UNASSIGNED) || statusBooking.equalsIgnoreCase(Constants.JOB_STATUS_PENDING))
{
avatar.setBackground(ContextCompat.getDrawable(context, R.drawable.vector_portrait_placeholder));
name.setText(context.getString(R.string.not_assigned_yet));
status.setText(booking.getStatus());
timeSlot.setVisibility(View.GONE);
String[] bookingDateSplit = booking.getVisitDate().split("-");
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.YEAR, Integer.parseInt(bookingDateSplit[0]));
calendar.set(Calendar.MONTH, (Integer.parseInt(bookingDateSplit[1]) - 1));
calendar.set(Calendar.DAY_OF_MONTH, Integer.parseInt(bookingDateSplit[2]));
dayOfWeek.setText(util.getDayNameFromInt(calendar.get(Calendar.DAY_OF_WEEK)));
dayOfMonth.setText(bookingDateSplit[2]);
month.setText(util.getMonthShortNameFromInt(calendar.get(Calendar.MONTH)));
}
else
{
User consumer = booking.getConsumer();
if (consumer.getAvatar() != null && consumer.getAvatar().length() > 0)
{
Glide.with(context).load(consumer.getAvatar()).circleCrop().placeholder(R.drawable.vector_portrait_placeholder).into(avatar);
} else
{
avatar.setBackground(util.getTextDrawable(context, consumer.getFirstName()));
}
name.setText(String.format(Locale.getDefault(), "%d - %s %s", booking.getOrderId(), consumer.getFirstName(), consumer.getLastName()));
status.setText(booking.getStatus());
charges.setText(activeAppointment.getAppointmentType().equalsIgnoreCase(Constants.APPOINTMENT_TYPE_VISIT) ? booking.getVisitCharges() : booking.getBaseRate());
timeSlot.setText(activeAppointment.getSlotTitle());
String[] appointmentDateSplit = activeAppointment.getDate().split("-");
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.YEAR, Integer.parseInt(appointmentDateSplit[0]));
calendar.set(Calendar.MONTH, (Integer.parseInt(appointmentDateSplit[1]) - 1));
calendar.set(Calendar.DAY_OF_MONTH, Integer.parseInt(appointmentDateSplit[2]));
dayOfWeek.setText(util.getDayNameFromInt(calendar.get(Calendar.DAY_OF_WEEK)));
dayOfMonth.setText(appointmentDateSplit[2]);
month.setText(util.getMonthShortNameFromInt(calendar.get(Calendar.MONTH)));
}
if(booking.getStatus().equalsIgnoreCase(Constants.JOB_STATUS_SCHEDULED)
|| booking.getStatus().equalsIgnoreCase(Constants.JOB_STATUS_IN_PROGRESS)
|| booking.getStatus().equalsIgnoreCase(Constants.JOB_STATUS_COMPLETED)
|| booking.getStatus().equalsIgnoreCase(Constants.JOB_STATUS_CANCELLED))
{
cancel.setVisibility(View.GONE);
}
else
{
cancel.setVisibility(View.VISIBLE);
}
}
@Override
public void onClick(View view)
{
Booking clickedBooking = bookings.get(getAdapterPosition());
if (view.getId() == R.id.cancel)
{
new MaterialDialog.Builder(context)
.title(R.string.cancel_booking)
.content(R.string.are_you_sure_cancel_booking)
.positiveText(R.string.cancel_booking)
.positiveColor(ContextCompat.getColor(context, R.color.quantum_googred500))
.onPositive((dialog, which) -> cancelOrder(util.getToken(context), clickedBooking.getOrderId(), getAdapterPosition()))
.negativeText(R.string.dismiss)
.show();
} else
{
if (bookings.get(getAdapterPosition()).getStatus().equalsIgnoreCase(Constants.JOB_STATUS_UNASSIGNED) || bookings.get(getAdapterPosition()).getStatus().equalsIgnoreCase(Constants.JOB_STATUS_PENDING))
{
Toasty.info(context, R.string.no_booking_details_yet).show();
} else
{
context.startActivity(new Intent(context, BookingDetailsActivity.class)
.putExtra(Constants.ATTACHED_BOOKING, bookings.get(getAdapterPosition())));
}
}
}
}
public class LoadingViewHolder extends RecyclerView.ViewHolder
{
LoadingViewHolder(View itemView)
{
super(itemView);
}
}
public void setMoreDataAvailable(boolean moreDataAvailable)
{
isMoreDataAvailable = moreDataAvailable;
}
/* notifyDataSetChanged is a final method so we can't override it
call adapter.notifyDataChanged() after updating the list */
public void notifyDataChanged()
{
notifyDataSetChanged();
isLoading = false;
}
public interface OnLoadMoreListener
{
void onLoadMore();
}
public void setLoadMoreListener(OnLoadMoreListener loadMoreListener)
{
this.loadMoreListener = loadMoreListener;
}
private void cancelOrder(String authorization, long bookingId, int position)
{
APIClient.getClient().cancelOrder(authorization, FSSApplication.companyToken, new RequestCancelOrder(bookingId)).enqueue(new Callback<ResponseGenericString>()
{
@Override
public void onResponse(Call<ResponseGenericString> call, Response<ResponseGenericString> response)
{
if (response.isSuccessful())
{
if (response.body().getStatus())
{
Toasty.success(context, response.body().getMessage()).show();
bookings.remove(position);
notifyDataChanged();
} else
{
Toasty.error(context, response.body().getMessage()).show();
}
}
}
@Override
public void onFailure(Call<ResponseGenericString> call, Throwable t)
{
Toasty.error(context, t.getMessage()).show();
}
});
}
}
暂无答案!
目前还没有任何答案,快来回答吧!