ASIHTTPRequest在tableview上同时下载图像需要时间

时间:2011-12-15 05:04:29

标签: iphone uitableview uiimageview asihttprequest

我在项目中使用了ASIHTTPRequest框架来处理所有与网络相关的任务。

我有自定义单元格,其缩略图来自网络服务器,大约有500张图片,所以我必须重复使用单元格来处理它。当我们滚动浏览tableview时,可以重复使用单元格,我们可以看到将被新图像替换的先前单元格的图像。

如果网络连接较低则更糟糕,因为下载图像需要花费大量时间..那么你可以看到特别错误的图像因为重复使用单元格所以我需要找到方法以便这个图像替换不应该对用户可见。

我正在使用ASIDownalod SharedCache方法。

修改

NSString *reuseIdentifier = @"offerCell";

BRZOfferCell *offerCell = (BRZOfferCell*)[tableView dequeueReusableCellWithIdentifier:reuseIdentifier];

if (offerCell==nil) {

    offerCell = [[[BRZOfferCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:reuseIdentifier celltype:kDealCellTypeDealsList] autorelease];
}

[offerCell setImage:[UIImage imageNamed:IMAGE_NO_IMAGE]];

//---get the letter in the current section---
//NSString *alphabet = [mDealsIndex objectAtIndex:[indexPath section]];

//---get all deals beginning with the letter---
NSString* lSectionIndex = [NSString stringWithFormat:@"%i",[indexPath section]];

NSMutableArray *deals = [mIndexedOffersDic objectForKey:lSectionIndex];


if ([deals count]>0) {
    //---extract the relevant deal from the deals array object---
    Offer* lOffer = [deals objectAtIndex:indexPath.row];

    [offerCell setOffer:lOffer];

    offerCell.accessoryView = UITableViewCellAccessoryNone;

    if (mTableView.dragging == NO && mTableView.decelerating == NO)
    {
        //Function : format image url to _thumb@2x.png and Initiate Image request download 
        //and set  cache policy
        [mListViewHelper InitImageRequest: lOffer.PromoImage indexPath: indexPath];
    }

}

return offerCell;

4 个答案:

答案 0 :(得分:1)

正如你所说UITableView为了表现良好而重用单元格,所以你需要在重用之前清除单元格,否则它将显示错误的数据。

您还应该使用异步调用和一些委派来更新单元格。

我实际上会把它提高一级并使用NSOperationQueue,它允许你设置最大并发下载次数,并在离开页面时取消请求。

您可能想要做的是创建数据助手

@protocol BookDataHelperDelegate <NSObject>
@required
- (void) bookDataHelperDidLoadImage:(BookDataHelper *)dataHelper;
@end

@interface BookDataHelper

@property (nonatomic, retian) UIImage *bookCover;
@property (nonatomic, retain) Book *book;
@property (nonatomic, assign) NSObject<BookDataHelperDelegate> *delegate;

- (void) fetchImageAsynchronouslyFromWebWithDelegate:(NSObject<BookDataHelperDelegate> *)delegate;

@end

这将是您在桌面上重新加载数据的方式

- (UITableViewCell *)tableView:(UITableView *)tableView
     cellForRowAtIndexPath:(NSIndexPath *)indexPath
{

    static NSString *SimpleTableIdentifier = @"SimpleTableIdentifier";
    CustomCell *cell = [tableView
    dequeueReusableCellWithIdentifier:SimpleTableIdentifier];
    if (cell == nil) 
    {
       cell = [[[CustomCell alloc]initWithStyle:UITableViewCellStyleDefault
       reuseIdentifier:SimpleTableIdentifier] autorelease];
    }

    BookDataHelper *dataHelper = [myArray objectAtIndex:indexPath.row];

    if (!dataHelper.bookCover)
    {
         [cell.imageView setImage:nil];
         [dataHelper fetchImageAsynchronouslyFromWebWithDelegate:self];
    } 
    else
    {
         [cell.imageView setImage:dataHelper.bookCover];
    }

    cell.bookTitleLabel.text = dataHelper.book.title;
    return cell;

}

- (void)bookDataHelperDidLoadImage:(BookDataHelper *)datahelper
{
   [tableView reloadDate];
   // here you would either reload the table completely
   // Or you could reload specific cells
}

答案 1 :(得分:0)

在tableview单元格委托中,当您获得重用或新单元格时,请在返回之前清除图像。在异步回调中使用正确的自加载映像进行更新。您可能希望确保图像已保存或保留在其他位置,但如果您不希望应用程序继续重新加载它们。

答案 2 :(得分:0)

在ASIHTTPRequest框架中,它同时处理Synchronize和ASynchronize类型,因此告诉我哪一个用于获取图像数据&amp;还告诉我你按时发送整个500图像请求或根据你的单元格发送

或者如果您发送500个图像请求的时间超过此值,则根据单元格要求不正确发送该单元格图像的请求,这是不可行的。

答案 3 :(得分:0)

我使用ASIDownloadCache方法来解决我的问题。实际上这个问题有2个解决方案

  1. 设置自己的缓存路径而不是使用SharedCache,但我没有这样做,因为我已经在使用sharedCache,并找到了另一种有效的方法,可以避免我改变我当前的实现

  2. 在这种方法中,我使用了ASIDownloadCache方法中的两种方法(令人惊讶的是ASIHTTPREquest网站在他们的简短信息中没有提到这些方法)

    2.1第一种方法- (BOOL)isCachedDataCurrentForRequest:(ASIHTTPRequest *)request
         验证此特定图像URL是否已经缓存,如果是,请使用第二种方法 2.2 - (NSData *)cachedResponseDataForURL:(NSURL *)url获取缓存的图像,以便我们可以在cellForRowAtIndexPath中设置图像,并且由于单元格的可重用性,您不会看到图像替换问题。

  3. 以下是代码:

    // Customize the appearance of table view cells.
    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
        NSString *reuseIdentifier = @"offerCell";
    
    
    BRZOfferCell *offerCell = (BRZOfferCell*)[tableView dequeueReusableCellWithIdentifier:reuseIdentifier];
    
    if (offerCell==nil) {
    
        offerCell = [[[BRZOfferCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:reuseIdentifier celltype:kDealCellTypeDealsList] autorelease];
    }
    
    [offerCell setImage:[UIImage imageNamed:IMAGE_NO_IMAGE]];
    
    //---get the letter in the current section---
    //NSString *alphabet = [mDealsIndex objectAtIndex:[indexPath section]];
    
    //---get all deals beginning with the letter---
    NSString* lSectionIndex = [NSString stringWithFormat:@"%i",[indexPath section]];
    
    NSMutableArray *deals = [mIndexedOffersDic objectForKey:lSectionIndex];
    
    
    if ([deals count]>0) {
        //---extract the relevant deal from the deals array object---
        Offer* lOffer = [deals objectAtIndex:indexPath.row];
    
        [offerCell setOffer:lOffer];
    
        offerCell.accessoryView = UITableViewCellAccessoryNone;
    
        if ([mListViewHelper isCached:lOffer.PromoImage]) { // Is image available in Cache ?
    
            // Image  is available use image fomr cache directly 
            [offerCell setImage:[UIImage imageWithData:[mListViewHelper cacheDataWithNSURL:lOffer.PromoImage]]];
        }
        else{
            //Function : Initiate Image request download and set cache policy
    
            if (mTableView.dragging == NO && mTableView.decelerating == NO)
                [mListViewHelper InitImageRequest: lOffer.PromoImage indexPath: indexPath];
        }
    }
    
    return offerCell;
    }