SDWebImage前世今生之V1.0版本

简介

SDWebImage是一个具有缓存支持的异步图像下载器。为了方便,我们为UIImageView、UIButton、MKAnnotationView等UI元素添加了类别。

1.0版本2009年12月31日发布

1.0版本中代码非常简单,没有使用NSURLConnection网络请求,只会从内存当中读取图片以及磁盘读写取文件,以及清除内存与磁盘缓存。
主要包括下列功能类:
UIImageView+WebCache 集成了图片下载
SDWebImageManager 下载管理器
SDWebImageDownloader 下载器(专门负责下载功能)
SDImageCache 负责缓存(内存缓存、磁盘缓存)
SDWebImageManagerDelegate 图片下载完成了
SDWebImageDownloaderDelegate 图片下载完成了

2.0版本2010年6月9日发布

2.0版本类结构上没有发生改变,最大改变增加了NSURLConnection网络请求和下面的一些优化

1. SDWebImageDownloaderDelegate.h 新增错误回调

@protocol SDWebImageDownloaderDelegate <NSObject>
@optional

- (void)imageDownloader:(SDWebImageDownloader *)downloader didFinishWithImage:(UIImage *)image;

//-----------------------2.0版本更新-新增错误回调-----------------------
- (void)imageDownloader:(SDWebImageDownloader *)downloader didFailWithError:(NSError *)error;
//---------------------------------end------------------------------

@end

2. SDWebImageManager.m去掉downloadWithURL、cancelForDelegate、didFinishWithImage方法的同步代码块

 - (void)downloadWithURL:(NSURL *)url delegate:(id<SDWebImageManagerDelegate>)delegate{
    if (url == nil || [failedURLs containsObject:url]){
        return;
    }
    SDWebImageDownloader *downloader = [downloaderForURL objectForKey:url];
    if (!downloader){
        downloader = [SDWebImageDownloader downloaderWithURL:url delegate:self];
        [downloaderForURL setObject:downloader forKey:url];
    }
//-----------------------2.0版本更新-去除@synchronized同步块-----------------------
    [delegates addObject:delegate];
    [downloaders addObject:downloader];
//-----------------------------------end-----------------------------
}

- (void)cancelForDelegate:(id<SDWebImageManagerDelegate>)delegate{
//-----------------------2.0版本更新-去除@synchronized同步块-----------------------
    NSUInteger idx = [delegates indexOfObjectIdenticalTo:delegate];
    if (idx == NSNotFound){
        return;
    }
    SDWebImageDownloader *downloader = [downloaders objectAtIndex:idx];
    [delegates removeObjectAtIndex:idx];
    [downloaders removeObjectAtIndex:idx];
    if (![downloaders containsObject:downloader]){
        [downloader cancel];
        [downloaderForURL removeObjectForKey:downloader.url];
    }
//-----------------------------------end-----------------------------
}

- (void)imageDownloader:(SDWebImageDownloader *)downloader didFinishWithImage:(UIImage *)image{
//-----------------------2.0版本更新-去除@synchronized同步块-----------------------
    for (NSInteger idx = [downloaders count] - 1; idx >= 0; idx--){
        SDWebImageDownloader *aDownloader = [downloaders objectAtIndex:idx];
        if (aDownloader == downloader){
            id<SDWebImageManagerDelegate> delegate = [delegates objectAtIndex:idx];
            if (image && [delegate respondsToSelector:@selector(webImageManager:didFinishWithImage:)]){
                [delegate performSelector:@selector(webImageManager:didFinishWithImage:) withObject:self withObject:image];
            }
            [downloaders removeObjectAtIndex:idx];
            [delegates removeObjectAtIndex:idx];
        }
    }
//-----------------------------------end-----------------------------

    if (image){
        [[SDImageCache sharedImageCache] storeImage:image forKey:[downloader.url absoluteString]];
    } else {
        [failedURLs addObject:downloader.url];
    }
    [downloaderForURL removeObjectForKey:downloader.url];
}

3. SDWebImageDownloader.h 的父类由NSOperation更新为NSObject,同时添加了NSURLConnection成员变量。

//-----------------------2.0版本更新-新增网络请求,继承自NSObject-----------------------
@interface SDWebImageDownloader : NSObject{
@private
    NSURL *url;
    NSURLConnection *connection;
    NSMutableData *imageData;
}
//-------------------------------end--------------------------------

@property (nonatomic, retain) NSURL *url;
@property (nonatomic, assign) id<SDWebImageDownloaderDelegate> delegate;

+ (id)downloaderWithURL:(NSURL *)url delegate:(id<SDWebImageDownloaderDelegate>)delegate;

//--------------2.0版本更新-新增网络请求,废弃setMaxConcurrentDownloads方法-----------------------
+ (void)setMaxConcurrentDownloads:(NSUInteger)max __attribute__((deprecated));
- (void)start;
- (void)cancel;
//-------------------------------end--------------------------------
@end

4. SDWebImageDownloader.m增加开始和取消网络请求方法start 、cancel和网络请求回调方法didReceiveData、connectionDidFinishLoading、didFailWithError

//--------------------------2.0版本更新-网络请求--------------------------
@interface SDWebImageDownloader ()
@property (nonatomic, retain) NSURLConnection *connection;
@property (nonatomic, retain) NSMutableData *imageData;
@end
//--------------------------------end---------------------------------

@implementation SDWebImageDownloader
@synthesize url, delegate, connection, imageData;

//--------------------------2.0版本更新-去除NSOperationQueue--------------------------
+ (id)downloaderWithURL:(NSURL *)url delegate:(id<SDWebImageDownloaderDelegate>)delegate{
    SDWebImageDownloader *downloader = [[SDWebImageDownloader alloc] init];
    downloader.url = url;
    downloader.delegate = delegate;
    [downloader start];
    return downloader;
}
//--------------------------------end---------------------------------

+ (void)setMaxConcurrentDownloads:(NSUInteger)max{
    // NOOP
}

//--------------------------2.0版本更新-网络请求--------------------------
- (void)start{
    NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:15];
    self.connection = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:NO];
    [connection scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];
    [connection start];

    if (connection){
        self.imageData = [NSMutableData data];
    } else {
        if ([delegate respondsToSelector:@selector(imageDownloader:didFailWithError:)]){
            [delegate performSelector:@selector(imageDownloader:didFailWithError:) withObject:self withObject:nil];
        }
    }
}
- (void)cancel{
    if (connection){
        [connection cancel];
        self.connection = nil;
    }
}
//--------------------------end--------------------------

//--------------------------2.0版本更新-请求回调--------------------------
- (void)connection:(NSURLConnection *)aConnection didReceiveData:(NSData *)data{
    [imageData appendData:data];
}

- (void)connectionDidFinishLoading:(NSURLConnection *)aConnection{
    UIImage *image = [[UIImage alloc] initWithData:imageData];
    self.imageData = nil;
    self.connection = nil;
    if ([delegate respondsToSelector:@selector(imageDownloader:didFinishWithImage:)]){
        [delegate performSelector:@selector(imageDownloader:didFinishWithImage:) withObject:self withObject:image];
    }
}

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error{
    if ([delegate respondsToSelector:@selector(imageDownloader:didFailWithError:)]){
        [delegate performSelector:@selector(imageDownloader:didFailWithError:) withObject:self withObject:error];
    }
    self.connection = nil;
    self.imageData = nil;
}
//--------------------------end--------------------------

@end

5. SDImageCache.m新增后台通知UIApplicationDidEnterBackgroundNotification,当进入后台模式清空内存缓存,优化内存存储。

- (instancetype)init{
    self = [super init];
    if (self) {
        //内存缓存
        memCache = [[NSMutableDictionary alloc] init];
        //磁盘缓存
        NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
        //磁盘目录
        diskCachePath = [[paths objectAtIndex:0] stringByAppendingPathComponent:@"ImageCache"];
        //创建目录
        if (![[NSFileManager defaultManager] fileExistsAtPath:diskCachePath]){
            [[NSFileManager defaultManager] createDirectoryAtPath:diskCachePath withIntermediateDirectories:YES attributes:nil error:NULL];
        }
        
        //初始化缓存队列
        cacheInQueue = [[NSOperationQueue alloc] init];
        cacheInQueue.maxConcurrentOperationCount = 2;
        //订阅应用程序事件
        //应用程序终止,里面回调didReceiveMemoryWarning方法,清空内存
        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(didReceiveMemoryWarning:)
                                                     name:UIApplicationDidReceiveMemoryWarningNotification
                                                   object:nil];
        //应用程序终止,里面回调willTerminate方法,清空磁盘
        [[NSNotificationCenter defaultCenter] addObserver:self
                                                 selector:@selector(willTerminate)
                                                     name:UIApplicationWillTerminateNotification
                                                   object:nil];

        //-----------------------2.0版本更新-新增后台通知-----------------------
        UIDevice *device = [UIDevice currentDevice];
        if ([device respondsToSelector:@selector(isMultitaskingSupported)] && device.multitaskingSupported){
            [[NSNotificationCenter defaultCenter] addObserver:self
                                                     selector:@selector(clearMemory)
                                                         name:UIApplicationDidEnterBackgroundNotification
                                                       object:nil];
        }
        //--------------------------------end--------------------------------
    }
    return self;
}

2.1版本2010年6月12日发布

1. UIImageView+WebCache 新增取消图片加载

@interface UIImageView (WebCache) <SDWebImageManagerDelegate>

- (void)setImageWithURL:(NSURL *)url;
- (void)setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder;

//----------------------2.1版本更新-新增-取消图片加载--------------------
- (void)cancelCurrentImageLoad;
//------------------------------end----------------------------------

@end
//-----------------------2.1版本更新-取消图片加载-----------------------
- (void)cancelCurrentImageLoad{
    [[SDWebImageManager sharedManager] cancelForDelegate:self];
}
//------------------------------end----------------------------------

2. SDImageCache 缓存器做了优化,兼容iPhone4增加了宏定义

        //-----------------------2.1版本更新-系统版本兼容宏定义-----------------------
        #ifdef __IPHONE_4_0
        UIDevice *device = [UIDevice currentDevice];
        if ([device respondsToSelector:@selector(isMultitaskingSupported)] && device.multitaskingSupported){
            [[NSNotificationCenter defaultCenter] addObserver:self
                                                     selector:@selector(clearMemory)
                                                         name:UIApplicationDidEnterBackgroundNotification
                                                       object:nil];
        }
        #endif
        //--------------------------------end--------------------------------
    }

2.2版本2010年8月29日发布

更新说明:如果图片格式是PNG或GIF,当存储到磁盘进行缓存时候,不要将图像转换为JPEG,因为他能够节省CPU和内存以及alpha通道/图像的清晰度。

1. SDWebImageDownloader 新增加了属性,在主线程下载和优化了回调处理

@property (nonatomic, retain) NSURL *url;
@property (nonatomic, assign) id<SDWebImageDownloaderDelegate> delegate;
//-------------2.2版本更新-新增-新增属性-------------------
@property (nonatomic, retain) NSMutableData *imageData;
//--------------------------end-------------------------
+ (id)downloaderWithURL:(NSURL *)url delegate:(id<SDWebImageDownloaderDelegate>)delegate{
    SDWebImageDownloader *downloader = [[SDWebImageDownloader alloc] init];
    downloader.url = url;
    downloader.delegate = delegate;
//-------------2.2版本更新-在主线程下载-------------------
    [downloader performSelectorOnMainThread:@selector(start) withObject:nil waitUntilDone:YES];
//--------------------------end-------------------------
    return downloader;
}

- (void)connectionDidFinishLoading:(NSURLConnection *)aConnection{
    //------------------2.2版本更新-优化----------------------
    self.connection = nil;
    //下载器下载完成
    if ([delegate respondsToSelector:@selector(imageDownloaderDidFinish:)]){
        [delegate performSelector:@selector(imageDownloaderDidFinish:) withObject:self];
    }
    if ([delegate respondsToSelector:@selector(imageDownloader:didFinishWithImage:)]){
        UIImage *image = [[UIImage alloc] initWithData:imageData];
        [delegate performSelector:@selector(imageDownloader:didFinishWithImage:) withObject:self withObject:image];
    }
    //--------------------------end--------------------------
}


2. 缓存器->SDImageCache 新增了属性和方法重载,增加了二进制NSData数据存储到磁盘

@interface SDImageCache : NSObject{
    NSMutableDictionary *memCache;
    NSString *diskCachePath;
    NSOperationQueue *cacheInQueue;
    //-------------2.2版本更新-新增-方法重载-功能抽象-------------------
    NSMutableDictionary *storeDataQueue;
    //--------------------------------end------------------------------
}

//-------------2.2版本更新-新增-方法重载-功能抽象-------------------
- (void)storeImage:(UIImage *)image imageData:(NSData *)data forKey:(NSString *)key toDisk:(BOOL)toDisk;
//-------------------------------end---------------------------
//-------------2.2版本更新-新增-方法重载-功能抽象-------------------
- (void)storeImage:(UIImage *)image forKey:(NSString *)key{
    [self storeImage:image imageData:nil forKey:key toDisk:YES];
}
- (void)storeImage:(UIImage *)image forKey:(NSString *)key toDisk:(BOOL)toDisk{
    [self storeImage:image imageData:nil forKey:key toDisk:toDisk];
}
- (void)storeImage:(UIImage *)image imageData:(NSData *)data forKey:(NSString *)key toDisk:(BOOL)toDisk{
    if (!image || !key){
        return;
    }
    if (toDisk && !data){
        return;
    }
    [memCache setObject:image forKey:key];
    if (toDisk){
        [storeDataQueue setObject:data forKey:key];
        [cacheInQueue addOperation:[[NSInvocationOperation alloc] initWithTarget:self selector:@selector(storeKeyToDisk:) object:key]];
    }
}
//-------------------------------end---------------------------

- (void)storeKeyToDisk:(NSString *)key{
    //-------------2.2版本更新-磁盘缓存-------------------
    NSFileManager *fileManager = [[NSFileManager alloc] init];
    NSData *data = [storeDataQueue objectForKey:key];
    if (data){
        //存储二进制->NSData
        [fileManager createFileAtPath:[self cachePathForKey:key] contents:data attributes:nil];
        @synchronized(storeDataQueue){
            [storeDataQueue removeObjectForKey:key];
        }
        //----------------------end------------------------
    } else {
        //存储图片->UIImage
        UIImage *image = [self imageFromKey:key fromDisk:YES];
        if (image){
            [fileManager createFileAtPath:[self cachePathForKey:key] contents:UIImageJPEGRepresentation(image, (CGFloat)1.0) attributes:nil];
        }
    }
}

3. SDWebImageDownloaderDelegate 新增了回调imageDownloaderDidFinish针对于imageData它而设计,后面版本迭代会更新具体实现暂时没有。

//-----------------------2.2版本更新-下载完成回调-----------------------
- (void)imageDownloaderDidFinish:(SDWebImageDownloader *)downloader;
//---------------------------------end------------------------------

2.3版本2010年9月17日发布

1. SDImageCacheDelegate 新增该代理类

//-------------------2.3版本更新-缓存回调-------------------
@class SDImageCache;
@protocol SDImageCacheDelegate <NSObject>
@optional
//缓存过程中有图片,缓存成功
- (void)imageCache:(SDImageCache *)imageCache didFindImage:(UIImage *)image forKey:(NSString *)key userInfo:(NSDictionary *)info;
//缓存过程中没有图片,缓存失败了
- (void)imageCache:(SDImageCache *)imageCache didNotFindImageForKey:(NSString *)key userInfo:(NSDictionary *)info;
@end
//---------------------------end-------------------------

2. UIImageView + WebCache 抽象缓存逻辑到管理器中

//-------------------2.3版本更新-优化处理-------------------
- (void)setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder{
    SDWebImageManager *manager = [SDWebImageManager sharedManager];
    [manager cancelForDelegate:self];
    self.image = placeholder;
    if (url){
        [manager downloadWithURL:url delegate:self];
    }
}
//---------------------------end-------------------------

3. SDWebImageManager 实现SDImageCacheDelegate协议

        缓存代理,异步检查磁盘上的缓存,这样我们就不会阻塞主线程缓存代理回调实现。
- (void)downloadWithURL:(NSURL *)url delegate:(id<SDWebImageManagerDelegate>)delegate{
    if (!url || !delegate || [failedURLs containsObject:url]){
        return;
    }
    //-------------------2.3版本更新-避免阻塞主线程-------------------
    //检查磁盘上的缓存异步,这样我们就不会阻塞主线程
    NSDictionary *info = [NSDictionary dictionaryWithObjectsAndKeys:delegate, @"delegate", url, @"url", nil];
    [[SDImageCache sharedImageCache] queryDiskCacheForKey:[url absoluteString] delegate:self userInfo:info];
    //---------------------------end-------------------------
}

//--------------------2.3版本更新--实现协议SDImageCacheDelegate功能----------
- (void)imageCache:(SDImageCache *)imageCache didFindImage:(UIImage *)image forKey:(NSString *)key userInfo:(NSDictionary *)info{
    id<SDWebImageManagerDelegate> delegate = [info objectForKey:@"delegate"];
    if ([delegate respondsToSelector:@selector(webImageManager:didFinishWithImage:)]){
        [delegate performSelector:@selector(webImageManager:didFinishWithImage:) withObject:self withObject:image];
    }
}

- (void)imageCache:(SDImageCache *)imageCache didNotFindImageForKey:(NSString *)key userInfo:(NSDictionary *)info{
    NSURL *url = [info objectForKey:@"url"];
    id<SDWebImageManagerDelegate> delegate = [info objectForKey:@"delegate"];
    //为相同的URL共享相同的下载加载程序,所以我们不会多次下载相同的URL
    SDWebImageDownloader *downloader = [downloaderForURL objectForKey:url];
    if (!downloader){
        downloader = [SDWebImageDownloader downloaderWithURL:url delegate:self];
        [downloaderForURL setObject:downloader forKey:url];
    }
    [delegates addObject:delegate];
    [downloaders addObject:downloader];
}
//------------------------------------end---------------------------------

3. SDImageCache

  • 新增了属性cacheOutQueue避免阻塞主线程,
  • 新增异步读取缓存方法queryDiskCacheForKey两个缓存:内存缓存、磁盘缓存读取是耗时操作
  • 新增了notifyDelegate方法通知所有的缓存代理
  • 新增了queryDiskCacheOperation方法2.3版本网络请求还没有完善
@interface SDImageCache : NSObject{
    NSMutableDictionary *memCache;
    NSString *diskCachePath;
    NSOperationQueue *cacheInQueue;
    
    //-------------------2.3版本更新-避免阻塞主线程--------------------
    NSOperationQueue *cacheOutQueue;
    //--------------------------------end--------------------------
}

- (UIImage *)imageFromKey:(NSString *)key;
- (UIImage *)imageFromKey:(NSString *)key fromDisk:(BOOL)fromDisk;

//---------------2.3版本更新-新增功能->异步方法--------------------
- (void)queryDiskCacheForKey:(NSString *)key delegate:(id<SDImageCacheDelegate>)delegate userInfo:(NSDictionary *)info;
//-------------------------------end---------------------------
@end
//---------------2.3版本更新-新增功能->异步方法--------------------
- (void)notifyDelegate:(NSDictionary *)arguments{
    NSString *key = [arguments objectForKey:@"key"];
    id <SDImageCacheDelegate> delegate = [arguments objectForKey:@"delegate"];
    NSDictionary *info = [arguments objectForKey:@"userInfo"];
    UIImage *image = [arguments objectForKey:@"image"];
    if (image){
        [memCache setObject:image forKey:key];
        if ([delegate respondsToSelector:@selector(imageCache:didFindImage:forKey:userInfo:)]){
            [delegate imageCache:self didFindImage:image forKey:key userInfo:info];
        }
    } else {
        if ([delegate respondsToSelector:@selector(imageCache:didNotFindImageForKey:userInfo:)]){
            [delegate imageCache:self didNotFindImageForKey:key userInfo:info];
        }
    }
}
- (void)queryDiskCacheOperation:(NSDictionary *)arguments{
    NSString *key = [arguments objectForKey:@"key"];
    NSMutableDictionary *mutableArguments = [arguments mutableCopy];
    UIImage *image = [[UIImage alloc] initWithContentsOfFile:[self cachePathForKey:key]];
    if (image){
        [mutableArguments setObject:image forKey:@"image"];
    }
    [self performSelectorOnMainThread:@selector(notifyDelegate:) withObject:mutableArguments waitUntilDone:NO];
}
- (void)queryDiskCacheForKey:(NSString *)key delegate:(id <SDImageCacheDelegate>)delegate userInfo:(NSDictionary *)info{
    if (!delegate){
        return;
    }
    if (!key){
        if ([delegate respondsToSelector:@selector(imageCache:didNotFindImageForKey:userInfo:)]){
            [delegate imageCache:self didNotFindImageForKey:key userInfo:info];
        }
        return;
    }
    //首先检查内存缓存…
    UIImage *image = [memCache objectForKey:key];
    if (image){
        //从缓存中读取到了图片
        //立即通知delegate,不需要去异步
        if ([delegate respondsToSelector:@selector(imageCache:didFindImage:forKey:userInfo:)]){
            [delegate imageCache:self didFindImage:image forKey:key userInfo:info];
        }
        return;
    }
    //缓存中没有
    NSMutableDictionary *arguments = [NSMutableDictionary dictionaryWithCapacity:3];
    [arguments setObject:key forKey:@"key"];
    [arguments setObject:delegate forKey:@"delegate"];
    if (info){
        [arguments setObject:info forKey:@"userInfo"];
    }
    [cacheOutQueue addOperation:[[NSInvocationOperation alloc] initWithTarget:self selector:@selector(queryDiskCacheOperation:) object:arguments]];
}
//------------------------end------------------------
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,509评论 6 504
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,806评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,875评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,441评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,488评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,365评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,190评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,062评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,500评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,706评论 3 335
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,834评论 1 347
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,559评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,167评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,779评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,912评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,958评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,779评论 2 354

推荐阅读更多精彩内容