- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
我正在将图像加载到表格 View 单元格,每个单元格都有一个图像。我已经将几个教程改编成下面的代码,但我的速度仍然很慢。
我正在从文档目录加载这些图像。有关如何加快此过程的任何提示或想法?
编辑修改后的代码:
Beer *beer = (Beer *) [self.fetchedResultsController objectAtIndexPath:indexPath];
cell.displayBeerName.text = beer.name;
// did we already cache a copy of the image?
if (beer.image != nil) {
// good. use it. this will run quick and this will run most of the time
cell.beerImage.image = beer.image;
} else {
// it must be the first time we've scrolled by this beer. do the expensive
// image init off the main thread
cell.beerImage.image = nil; // set a default value here. nil is good enough for now
[self loadImageForBeer:beer atIndexPath:indexPath];
}
- (void)loadImageForBeer:(Beer *)beer atIndexPath:(NSIndexPath *)indexPath {
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul);
dispatch_async(queue, ^{
UIImage *image = [UIImage imageWithContentsOfFile:beer.imagePath];
beer.image = image;
dispatch_sync(dispatch_get_main_queue(), ^{
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
cell.beerImage.image = image;
});
});
}
最佳答案
您的算法看起来不错。您已经避免了许多典型的陷阱。如果您仍然遇到 UI 性能问题,我建议您采取以下措施:
您应该尝试将图像缓存在内存中。您可以使用 NSMutableArray
或 NSMutableDictionary
,但在 Best way to cache images on ios app? Caleb 讨论了 NSCache
类的优点,它简化了过程。如果您缓存图像,请确保您响应内存压力并在必要时清除缓存。您可以响应 didReceiveMemoryWarning
或将自己添加为通知中心的 UIApplicationDidReceiveMemoryWarningNotification
的观察者。
确保您的缓存图像是缩略图大小的,否则您的 UI 中总是会有一点卡顿(如果您需要调整大小的算法,请告诉我们)并且它会不必要地占用内存;
当您将图像更新分派(dispatch)回主队列时,您应该异步执行(为什么后台队列会在等待 block 被发送回主队列时挂起并占用资源完成...一旦您在快速滚动期间备份了几张图像,这尤其是一个问题);和
当您分派(dispatch)回主队列时,您应该检查以确保从 cellForRowAtIndexPath
获得的单元格不是 nil
(因为如果单元格加载逻辑得到备份过多(尤其是在速度较慢的设备上),理论上您可能会将有问题的单元格滚出屏幕,您的算法可能会崩溃。
我使用的算法与您的非常相似,具有几乎相同的 GCD 结构(带有上述注意事项)并且滚动非常流畅,即使在较旧的设备上也是如此。如果你想让我发布代码,我很乐意。
如果您仍然遇到问题,CPU 分析器非常适合识别瓶颈并让您知道应该将注意力集中在何处。网上有一些很棒的 WWDC session ,重点介绍如何使用 Instruments 来识别性能瓶颈,我发现它们对熟练使用 Instruments 非常有帮助。
这是我的代码。在 viewDidLoad
中,我初始化我的图像缓存:
- (void)initializeCache
{
self.imageCache = [[NSCache alloc] init];
self.imageCache.name = @"Custom Image Cache";
self.imageCache.countLimit = 50;
}
然后我在我的 tableView:cellForRowAtIndexPath
中使用它:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"ilvcCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
// set the various cell properties
// now update the cell image
NSString *imagename = [self imageFilename:indexPath]; // the name of the image being retrieved
UIImage *image = [self.imageCache objectForKey:imagename];
if (image)
{
// if we have an cachedImage sitting in memory already, then use it
cell.imageView.image = image;
}
else
{
cell.imageView.image = [UIView imageNamed:@"blank_image.png"];
// the get the image in the background
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
// get the UIImage
UIImage *image = [self getImage:imagename];
// if we found it, then update UI
if (image)
{
dispatch_async(dispatch_get_main_queue(), ^{
// if the cell is visible, then set the image
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
if (cell)
cell.imageView.image = image;
[self.imageCache setObject:image forKey:imagename];
});
}
});
}
return cell;
}
和
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
[self.imageCache removeAllObjects];
}
顺便说一句,您可能会考虑进一步优化,将缓存的图像预加载到单独的队列中,而不是在单独的线程中即时加载图像。我认为没有必要,因为这对我来说似乎已经足够快了,但它是加速 UI 的另一种选择。
关于iphone - TableView 滚动异步,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11486828/
我正在对 tableView 是否呈现单元格进行单元测试。 我发现 tableView.cellForRow(at:) 返回 nil,而 tableView.dataSource?tableView(
我有 Tableview 用于显示客户下的食品订单。其中包含水平 UIStackview。在 UIStackView UIStackview 中很少有一/两行标签和一个用于显示订单项的UITableV
我有 Viewcontroller,我在其中设置了 ScrollView 。在 scrollview 中,我有一个 tableview,它位于 Container 中,就在容器下方,当我将 table
我想在滚动时让我的第一个单元格始终位于 tableview 的顶部。 任何帮助都是可观的。提前致谢... 最佳答案 这是为 UITableView 创建标题 View 的方法 - (UIView *)
在我的应用程序中,我点击一行,它会在其下方展开另一行。我想生成一种随机颜色,当我单击一行时,行背景会变成该颜色,而它下面的展开行会变成相同的颜色。如何让行生成相同的随机颜色? 我创建了一个函数来生成随
我正在为这个问题苦苦挣扎,所以我需要你的帮助。基本上我已经编写了一个复杂的 TableView Controller (使用 NSFetchedResults 协议(protocol)等)并且已经在我
我正在使用 JavaFx 2.2。我遇到了一个问题,我无法在 TableView 列中放置不同的组件。例如我有两列 1) 回答 2) 答案类型 如果 AnswerType 包含“Multiple Ch
试图弄清楚如何在 javafx 2 中禁用表列的重新排序? 最佳答案 这是解决方案: tblView.getColumns().addListener(new ListChangeListener()
我一直在寻找有关将数据刷新到 tableview 的信息。我试图直接修改模型,但我遇到了一个错误。我修改了模型,但表格没有刷新,只有当我移动一列时,表格才会显示修改后的值。 为了给你展示一个例子(13
给定一个TableView,我需要检测单元格上的双击。 tableView.setOnMouseClicked(new EventHandler() { @Override publi
我成功创建了一个 TableView,其中将特定列分配给了数据模型类。该程序可以将 csv 文件解析为其中并在表中正确显示所有内容。在此阶段,滚动不是问题。 然后我想选择特定行并将它们发送到另一个表。
我尝试了所有方法来用数据填充 TableView。下一个代码在表中插入一个新行,但数据没有出现在表中。我试图为此找到解释,但没有成功。 请帮忙。我不知道怎么了。 在 controller.java 中
我尝试了所有方法来用数据填充 TableView。下一个代码在表中插入一个新行,但数据没有出现在表中。我试图为此找到解释,但没有成功。 请帮忙。我不知道怎么了。 在 controller.java 中
我有一个通过 Tableview 显示玩家的应用程序。用户可以“添加”一个新玩家并输入他的姓名、高度、体重、图片等...保存后将被添加到 Tableview 中。他们还可以点击每个玩家,然后将他们带到
对于大学,我必须编写一个小应用程序,其想法是创建一个小公式集合。这个概念是有一个类别列表,选择类别后您会收到一个公式列表。选择所需的公式后,您将看到公式计算器的 View 。 我正在努力获得第一个UI
如果我只加载一个 TableView ,我的 View 中必须有两个 TableView ,它工作正常。但是当我尝试使用下面的方法加载两个表格 View 时,它给出了以下异常。 未捕获异常“NSRan
我是 JavaFx 的新手,我正在尝试创建一个 TableView ,而 fxml 是使用场景生成器创建的。如果我运行该程序,该表不会获取值。我发现这个问题在某种程度上符合我的要求( javaFX 2
是否可以对 tableView 进行反向排序?我搜索了很多解决方案,但没有任何效果。 效果就像whatsapp聊天。 一个普通的tableView是: ---------- label 1 -----
我有一个有趣的问题。我有两个 TableView ,一个在另一个里面。我有一个结构,我想用它来将数据添加到我的 TableView 中。该结构有 2 个字符串项和另一个具有 3 个字符串项的结构的数组
我正在使用的方法 func tableView(tableView: UITableView, editActionsForRowAtIndexPath indexPath: NSIndexPath
我是一名优秀的程序员,十分优秀!