[每天记录一个Bug]Cell中由于block加载网络请求产生的复用

Bug 出现场景:

cell中使用加载图片的网络请求出现复用,截图如下:

复用原因:

Cell Model中只有一个用户的uid,所有用户相关信息:例如头像\名称\信息等是通过 block请求,通过uid 回调中取到的字段,但由于是在cell中通过系统的block回调中下载得到的头像,所以会有延时问题.

当使用 self.collection reloadData ,这个语句的时候,由于4个cell的头像还没加载成功,瞬间又重新复用4个cell出来,就会产生复用的情况。

也就是说  4个cell地址如下:

0XA1

0XA2

0XA3

0XA4

4个cell地址正序排列,分别取block请求拉取头像的时候,此时还没有拉取成功,瞬间执行语句  self.collection reloadData。cell 会产生复用机制,地址排列顺序如下:

0XA4

0XA3

0XA2

0XA1

此时就会产生复用,由于第一个cell网络请求较快,但是第4个cell请求比较慢,就会产生复用:

因为

0XA1 头像加载成功

0XA2

0XA3

0XA4 头像未加载成功

reloadData后复用

0XA4 头像加载成功,但是由于复用之前block还没有加载成功,导致在之前cell中的0XA4的头像直接覆盖了,复用后的0XA4的头像。

0XA3

0XA2

0XA1 由于复用钱0XA1头像加载速度较快,所以这个cell不会出现复用情况。适合网络加载快慢相关

cell中使用block进行网络请求,就容易出现此问题。

即时在 cell中的 prepareReuse()方法中将cell置nil,也会出现复用问题,因为根本原因是在block块中出现的复用问题。

解决方案:

在 block 块中 ,记录回调前的 user.uid 数据,然后和 cell此时记录的变量 model.uid 进行对比,因为model.uid是cell自带的字段,不会被复用的字段,而block中的user.uid是block回调后的字段,可能是之前cell中保留的字段。

进行对比,就知道block是复用前的,还是复用后的。

block里的变量不会变,但是复用后的cell Model会变。

解决方案 :

user.uid block回调产生的用户字段,_chatModel.chatCreater 是Model中的字段,不会被block所截取的临时变量。

if ([_chatModel.chatCreaterisEqualToString:user.uid]) {

//没被复用

}

else {

//被复用

}

代码如下:

IDSLOG(@"Home msg. model.chatCreater: %@,cell:%@", model.chatCreater,self);

@weakify(self);

[[IDSUserCachesharedCache] findUser:model.chatCreatercallback:^(NSArray<IDSLoginUser *> *users) {

@strongify(self);

if (IS_NS_COLLECTION_EMPTY(users)) {

return;

}

IDSLoginUser *user = [users cl_objectAtIndex:0];

IDSLOG(@"_chatModel.chatCreater : %@, user.uid:%@, model.chatCreater:%@", _chatModel.chatCreater, user.uid, model.chatCreater);

if ([_chatModel.chatCreaterisEqualToString:user.uid]) {

NSURL *bgimageUrl = nil;

if (!IS_NS_STRING_EMPTY(user.avatar_url)){

bgimageUrl = [AppUtilurlEncodeToNSURL:user.avatar_url];

}

staticUIImage *defImg;

staticdispatch_once_t onceToken;

dispatch_once(&onceToken, ^{

defImg = [[IDSImageManagersharedManager] defaultAvatar:CircleStyle];

});

[self.avatarImageViewsd_setImageWithURL:bgimageUrl

placeholderImage:defImg

options:SDWebImageRetryFailed|SDWebImageLowPriority];

self.nameLabel.text = user.username;

self.nameLabel.frame = CGRectMake(CGRectGetMaxX(self.avatarImageView.frame)+7,

CGRectGetMinY(self.chatLabel.frame)-7-self.nameLabel.contentSize.height, 0, 0);

self.avatarImageView.layer.cornerRadius = self.avatarImageView.frame.size.width/2.0;

[self.nameLabelsizeToFit];

self.timeLabel.frame = CGRectMake(CGRectGetMaxX(self.nameLabel.frame)+5, 0, 0, 0);

self.timeLabel.text = [TimeUtilcl_prettyDateWithReference:_chatModel.timestamp];

[self.timeLabelsizeToFit];

self.timeLabel.centerY = self.nameLabel.centerY;

}

}];

时间: 2024-10-08 01:01:31

[每天记录一个Bug]Cell中由于block加载网络请求产生的复用的相关文章

MVC中在一个视图中,怎么加载另外一个视图?

在RazorView.cshtml视图: <!--在视图中调用无返回值的方法,视图中调用无返回值的方法,要加上大括号--> <!--在一个视图中,直接加载另外一个视图--> @{ Html.RenderPartial("LoadViewBySelf");} 去加载LoadViewBySelf.cshtml视图: @{ ViewBag.Title = "LoadViewBySelf"; } <h2>LoadViewBySelf<

Java类加载机制——如何实现一个工程中不同模块加载不同版本的同名jar包。

如何实现一个工程中不同模块加载不同版本的同名jar包? 曾是阿里面试的时候遇到的一个面试题.当时就有点晕,如果是平时遇到这样的问题肯定是统一加载相同版本的就好了. 而如果系统特别庞大依赖冲突繁多,涉及多部门协调,真的有必要解决这样的问题. 这个问题困扰我很久,一直没有好的解决办法.最近研究java虚拟机.终于找到了答案. 在JVM里由类名和类加载器区别不同的Java类型.因此,JVM允许我们使用不同的加载器加载相同namespace的java类,而实际上这些相同namespace的java类可以

Composer中的自动加载

Composer是PHP的一个包依赖管理工具,类似Ruby中的RubyGems或者Node中的NPM,它并非官方,但现在已经非常流行.此文并不介绍如何使用Composer,而是关注于它的autoload的内容吧. 举例来说,假设我们的项目想要使用monolog这个日志工具,就需要在composer.json里告诉composer我们需要它: { "require": { "monolog/monolog": "1.*" } } 之后执行: php

Android中的分页加载

//----------------------MainActivity中--------------------------------------------------- package com.example.fenye; import java.util.ArrayList;import java.util.List; import android.os.Bundle;import android.app.Activity;import android.view.Menu;import

Java--自定义Class并且在内存中编译,加载,实例化

本文的目的: 使用者在程序运行期间,可以动态的写Java Class,不需要生成任何.Class文件就可以完全在内存中编译,加载,实例化. 1.需要用到的组件介绍 1)JavaCompiler:用于编译Java Code. 2)CharSequenceJavaFileObject:用于保存Java Code,提供方法给JavaCompiler获取String形式的Java Code. 3)ClassFileManager:用于JavaCompiler将编译好后的Class文件保存在指定对象中.

web中的懒加载

在Web应用程序中,系统的瓶颈常在于系统的响应速度.如果系统响应速度过慢,用户就会出现埋怨情绪,系统的价值也因此会大打折扣.因此,提高系统响应速度,是非常重要的. Web应用程序做的最多就是和后台数据库交互,而查询数据库是种非常耗时的过程.当数据库里记录过多时,查询优化更显得尤为重要.为了解决这种问题,有人提出了缓存的概念.缓存就是将用户频繁使用的数据放在内存中以便快速访问.在用户执行一次查询操作后,查询的记录会放在缓存中.当用户再次查询时,系统会首先从缓存中读取,如果缓存中没有,再查询数据库.

CLR中的程序集加载

本次来讨论一下基于.net平台的CLR中的程序集加载的机制: [注:由于.net已经开源,可利用vs2015查看c#源码的具体实现] 在运行时,JIT编译器利用程序集的TypeRef和AssemblyRef元数据表来确定哪一个程序集定义了所引用的类型.在AssemblyRef元数据表的记录项中,包含构成程序集的强名称的各个部分.JIT编译器获取包括名称(无扩展名和路径).版本.语言文化和公钥标记,将这些连接成一个字符串.JIT编译器将该标识匹配的一个程序集加载到AppDomain中.] CLR内

Android中ListView异步加载图片错位、重复、闪烁问题分析及解决方案

Android中ListView异步加载图片错位.重复.闪烁问题分析及解决方案 我们在使用ListView异步加载图片的时候,在快速滑动或者网络不好的情况下,会出现图片错位.重复.闪烁等问题,其实这些问题总结起来就是一个问题,我们需要对这些问题进行ListView的优化. 比如ListView上有100个Item,一屏只显示10个Item,我们知道getView()中convertView是用来复用View对象的,因为一个Item的对应一个View对象,而ImageView控件就是View对象通

解决MWPhotoBrowser中的SDWebImage加载大图导致的内存警告问题

解决MWPhotoBrowser中的SDWebImage加载大图导致的内存警告问题 iOS开发 · 2015-01-22 11:31 MWPhotoBrowser是一个非常不错的照片浏览器,在github的star接近3000个,地址:https://github.com/mwaterfall/MWPhotoBrowser.git MWPhotoBrowser来加载小图1M以下的都应该不会有内存警告的问题.如果遇到大图,3M.4M.5M的大图,很有可能导致内存警告.最近我就遇到这个问题,很是头疼