Android Recyclerview项目在刷新时混淆
可能重复 我有一个Recyclerview,通过适配器和列表填充项目。问题是,在刷新时(通过SwipeRefreshLayout),倒计时计时器的数据混淆,错误的值显示在另一项上,如下图所示。项目1突出显示的计时器应显示“已过期”,但在刷新时,它将采用项目2的计时器值 这是我的适配器中的onBindViewHolder代码。我是否正确地实施了它Android Recyclerview项目在刷新时混淆,android,android-recyclerview,Android,Android Recyclerview,可能重复 我有一个Recyclerview,通过适配器和列表填充项目。问题是,在刷新时(通过SwipeRefreshLayout),倒计时计时器的数据混淆,错误的值显示在另一项上,如下图所示。项目1突出显示的计时器应显示“已过期”,但在刷新时,它将采用项目2的计时器值 这是我的适配器中的onBindViewHolder代码。我是否正确地实施了它 public class FeedAdapter extends RecyclerView.Adapter<FeedAdapter.FeedMo
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);
}
}
公共类FeedAdapter扩展了RecyclerView.Adapter{
私有列表feedModelList;
私有主监听;
私有上下文;
弦cPrice;
公共FeedAdapter(ListfeedModelList、上下文上下文、MainFeedListener bidFeedListener){
this.feedModelList=feedModelList;
this.mContext=上下文;
this.listener=bidfeedstener;
}
@非空
@凌驾
公共FeedModelViewHolder onCreateViewHolder(视图组父级,int-viewType){
视图v=LayoutInflater.from(parent.getContext()).flate(R.layout.item\u bid\u feed,parent,false);
返回新的FeedModelViewHolder(v);
}
@凌驾
BindViewHolder上的公共无效(@NonNull final-FeedModelViewHolder,final-int位置){
最终FeedModel FeedModel=feedModelList.get(位置);
((TextView)holder.bidView.findviewbyd(R.id.bid_title)).setText(feedModel.getTitle());
((TextView)holder.bidView.findviewbyd(R.id.start_price)).setText(feedModel.getCurrency()+“”+Convert(feedModel.getStartPrice());
((TextView)holder.bidView.findviewbyd(R.id.tags)).setText(feedModel.getTags());
((TextView)holder.bidView.findviewbyd(R.id.location)).setText(feedModel.getLocation());
新的倒计时(feedModel.getDaildate(),1000){
公共void onTick(长毫秒未完成){
((TextView)holder.bidView.findviewbyd(R.id.deadline)).setText(formatMillisSecondsToTime(millisUntilFinished));
feedModel.设定时间(毫秒);
}
公共无效onFinish(){
((TextView)holder.bidView.findviewbyd(R.id.deadline)).setText(“过期”);
}
}.start();
如果(!TextUtils.isEmpty(feedModel.getImageUrl())){
Glide.with(mContext.load)(feedModel.getImageUrl())
.缩略图(0.5f)
.crossFade()
.diskCacheStrategy(diskCacheStrategy.ALL)
.into((ImageView)holder.bidView.findviewbyd(R.id.bid_缩略图));
}
((LinearLayout)holder.bidView.findviewbyd(R.id.article\u card\u root)).setOnClickListener(新视图.OnClickListener()){
@凌驾
公共void onClick(视图){
onBidRowClicked(feedModel);
}
});
}
@凌驾
public int getItemCount(){
返回feedModelList.size();
}
公共静态类FeedModelViewHolder扩展了RecyclerView.ViewHolder{
私人观点;
公共FeedModelViewHolder(视图v){
超级(五);
bidView=v;
}
}
字符串转换(双d){
int i;
d+=0.005;
i=(int)(d*100);
双b=(双)(i/100);
返回b.toString();
}
公共静态字符串格式毫秒到时间(长毫秒){
整数秒=(整数)(毫秒/1000)%60;
整数分钟=(整数)((毫秒/(1000*60))%60);
整数小时=(整数)(毫秒/(1000*60*60))//
//整数天=(整数)((毫秒/(1000*60*60))%24)//
返回twoDigitString(小时)+“:“+twoDigitString(分钟)+”:”
+两个数字串(秒);
}
私有静态字符串twoDigitString(长数字){
如果(数字==0){
返回“00”;
}
如果(数字/10==0){
返回“0”+数字;
}
返回字符串.valueOf(number);
}
}
我使用截取库填充列表,并通过构造函数将列表传递给适配器。这个问题很简单 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) {
...
}
}
这个问题很简单 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) {
...
}
}
您需要使用
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的onBindViewHolder
在开始时被调用,并且每次都被重新绘制
但是,这种方法在创建视图时启动计时器,可能不会产生理想的结果。建议在
适配器之外的某个地方跟踪此时间,并只传递对它们的引用。您需要使用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的onBindViewHolder
在开始时被调用,并且每次都被重新绘制
但是,这种方法在创建视图时启动计时器,可能不会产生理想的结果。建议在适配器之外的某个地方跟踪此时间,并只传递对它们的引用。请将您的holder类更改为:
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;
}
}
打开