我有一个Recyclerview,我通过适配器和列表填充了项目。问题是,在刷新时(通过SwipeRefreshLayout),倒数计时器的数据混合在一起,并且错误的值显示在另一个项目上,如下图突出显示。项目1突出显示的计时器应该显示为“已过期”,但在刷新时它将使用项目2的计时器值
这是我的适配器中的onBindViewHolder代码。我执行正确吗?
public class FeedAdapter extends RecyclerView.Adapter<FeedAdapter.FeedModelViewHolder> {
private List<FeedModel> feedModelList;
private MainFeedListener listener;
private Context mContext;
String cPrice;
public FeedAdapter(List<FeedModel>feedModelList, Context context, MainFeedListener bidFeedListener) {
this.feedModelList = feedModelList;
this.mContext = context;
this.listener = bidFeedListener;
}
@NonNull
@Override
public FeedModelViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_bid_feed, parent, false);
return new FeedModelViewHolder(v);
}
@Override
public void onBindViewHolder(@NonNull final FeedModelViewHolder holder, final int position) {
final FeedModel feedModel = feedModelList.get(position);
((TextView) holder.bidView.findViewById(R.id.bid_title)).setText(feedModel.getTitle());
((TextView) holder.bidView.findViewById(R.id.start_price)).setText(feedModel.getCurrency() +" "+Convert(feedModel.getStartPrice()));
((TextView) holder.bidView.findViewById(R.id.tags)).setText(feedModel.getTags());
((TextView) holder.bidView.findViewById(R.id.location)).setText(feedModel.getLocation());
new CountDownTimer(feedModel.getDeadline(), 1000) {
public void onTick(long millisUntilFinished) {
((TextView) holder.bidView.findViewById(R.id.deadline)).setText(formatMilliSecondsToTime( millisUntilFinished));
feedModel.setTime(millisUntilFinished);
}
public void onFinish() {
((TextView) holder.bidView.findViewById(R.id.deadline)).setText("EXPIRED");
}
}.start();
if (!TextUtils.isEmpty(feedModel.getImageUrl())) {
Glide.with(mContext).load(feedModel.getImageUrl())
.thumbnail(0.5f)
.crossFade()
.diskCacheStrategy(DiskCacheStrategy.ALL)
.into((ImageView) holder.bidView.findViewById(R.id.bid_thumbnail));
}
((LinearLayout) holder.bidView.findViewById(R.id.article_card_root)).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
listener.onBidRowClicked(feedModel);
}
});
}
@Override
public int getItemCount() {
return feedModelList.size();
}
public static class FeedModelViewHolder extends RecyclerView.ViewHolder {
private View bidView;
public FeedModelViewHolder(View v) {
super(v);
bidView = v;
}
}
String Convert(Double d){
int i;
d +=0.005;
i= (int) (d*100);
Double b = (double) (i / 100);
return b.toString();
}
public static String formatMilliSecondsToTime(long milliseconds) {
int seconds = (int) (milliseconds / 1000) % 60;
int minutes = (int) ((milliseconds / (1000 * 60)) % 60);
int hours = (int) ((milliseconds / (1000 * 60 * 60))); //
// int days = (int) ((milliseconds / (1000 * 60 * 60)) % 24); //
return twoDigitString(hours) + ":" + twoDigitString(minutes) + ":"
+ twoDigitString(seconds);
}
private static String twoDigitString(long number) {
if (number == 0) {
return "00";
}
if (number / 10 == 0) {
return "0" + number;
}
return String.valueOf(number);
}
}
我使用Volley库填充列表,并通过构造函数将列表传递给适配器
答案 0 :(得分:2)
请将您的持有人类别更改为此:
public static class FeedModelViewHolder extends RecyclerView.ViewHolder {
private View bidView;
private TextView title;
private TextView price;
private TextView tags;
private TextView location;
public FeedModelViewHolder(View v) {
super(v);
title = v.findViewById(R.id.bid_title);
price = v.findViewById(R.id.start_price)
tags = v.findViewById(R.id.tags)
location= v.findViewById(R.id.location);
bidView = v;
}
}
在BindViewHolder上
@Override
public void onBindViewHolder(@NonNull final FeedModelViewHolder holder, final int position) {
final FeedModel feedModel = feedModelList.get(position);
holder,title.setText(feedModel.getTitle());
holder.price.setText(feedModel.getCurrency() +" "+Convert(feedModel.getStartPrice()));
holder.tags.setText(feedModel.getTags());
holder.location.setText(feedModel.getLocation());
}
答案 1 :(得分:1)
这个问题很简单。
RecyclerView重用持有者,每次调用bind来更新其中的数据。
由于每次绑定任何数据时都会创建一个倒数计时器,所以最终会有多个计时器更新同一视图持有者。
最好的做法是将FeedViewHolder中的倒数计时器作为参考,在绑定数据(如果已启动)之前将其取消,然后将其重新安排为所需的持续时间。
public void onBindViewHolder(final FeedViewHolder holder, final int position) {
...
if (holder.timer != null) {
holder.timer.cancel();
}
holder.timer = new CountDownTimer(expiryTime, 500) {
...
}.start();
}
public static class FeedViewHolder extends RecyclerView.ViewHolder {
...
CountDownTimer timer;
public FeedViewHolder(View itemView) {
...
}
}
答案 2 :(得分:1)
您需要更多利用onCreateViewHolder
。首先(不是真正的问题,而是可读性的提示),将视图绑定到字段
public class FeedModelViewHolder extends RecyclerView.ViewHolder {
TextView bigTitle;
TextView deadline;
...
public FeedModelViewHolder(View v) {
super(v);
bitTitle = = (TextView) v.findViewById(R.id.bid_title);
deadline = = (TextView) v.findViewById(R.id.deadline);
...
new CountDownTimer(feedModel.getDeadline(), 1000) {
public void onTick(long millisUntilFinished) {
dealine.setText(formatMilliSecondsToTime( millisUntilFinished));
feedModelList.get(getAdapterPosition()).setTime(millisUntilFinished);
}
public void onFinish() {
dealine.setText("EXPIRED");
}
}.start();
}
}
,然后在onCreateViewHolder
中再次初始化您的计时器,因为它仅被调用一次。 onBindViewHolder
在开始时以及每次重绘时都会被调用。
但是,此方法在创建视图时启动计时器,并且可能不会产生理想的结果。建议在Adapter
之外的某个地方跟踪此时间,并仅将其传递给它们。