SDWebImage 圖片下載緩存框架 常用方法及原理

功能:圖片下載、圖片緩存、下載進(jìn)度監(jiān)聽、gif處理等等
項(xiàng)目地址:https://github.com/rs/SDWebImage

常見面試題:

  1. SDWebImage的最大并發(fā)數(shù)是多少?
    _downloadQueue.maxConcurrentOperationCount = 6;
  2. SDWebImages是如何識(shí)別圖片的?
    NSData+ImageContentType.m中,根據(jù)圖片文件十六進(jìn)制數(shù)據(jù)的第一個(gè)字節(jié)判斷


    圖片的十六進(jìn)制第一個(gè)字節(jié).png
  3. SDWebImage 緩存圖片命名規(guī)則?
    為了防止名稱重復(fù),對(duì)其進(jìn)行 md5 運(yùn)算
  4. 默認(rèn)下載的超時(shí)時(shí)長(zhǎng)是多少?15秒
  5. 默認(rèn)緩存的時(shí)間?一周
    _maxCacheAge = kDefaultCacheMaxCacheAge;
    static const NSInteger kDefaultCacheMaxCacheAge = 60 * 60 * 24 * 7; // 1 week
  6. SDWebImage用什么類型緩存圖片?NSCache
    SDImageCache內(nèi)處理內(nèi)存警告,以通知的方式,clearMemory
  7. cleanDisk的執(zhí)行過(guò)程
    i. 先遍歷所有的緩存文件,記錄過(guò)期的文件,計(jì)算緩存文件的總大小
    ii. 刪除過(guò)期的文件
    iii. 判斷maxCacheSize的值是否>0,如果大于0再判斷緩存的文件總大小是否大于maxCacheSize
    iv.如果緩存文件的總大小超過(guò)maxCacheSize,刪除最早的文件
    注意:.jpg、.gif等文件需要把擴(kuò)展名填上,png不需要

一、下載緩存

#import "UIImageView+WebCache.h"'
介紹:使用SDWebImage可以去加載遠(yuǎn)程圖片,而且還會(huì)緩存圖片,下次請(qǐng)求會(huì)看一下是否已經(jīng)存在于緩存中,如果是的話直接取本地緩存,如果不是的話則重新請(qǐng)求。

1、獲取當(dāng)前圖片的地址

- (NSURL *)sd_imageURL;

2、下載網(wǎng)絡(luò)圖片并緩存

  1. - (void)sd_setImageWithURL:(NSURL *)url;
  2. - (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder;
  3. - (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options;
  4. 下載圖片的線程執(zhí)行完后回調(diào)
    - (void)sd_setImageWithURL:(NSURL *)url completed: (SDWebImageCompletionBlock)completedBlock;
  5. - (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder completed:(SDWebImageCompletionBlock)completedBlock;
  6. - (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options completed:(SDWebImageCompletionBlock)completedBlock;
  7. 下載圖片并獲取圖片下載進(jìn)度 progressBlock
    - (void)sd_setImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(SDWebImageCompletionBlock)completedBlock;

例子:下載圖片并且打印圖片的下載進(jìn)度
NSURL *url = [NSURL URLWithString:@"http://picview01.baomihua.com/photos/20120624/m_14_634761470842343750_15728444.jpg"]; [self.imageView sd_setImageWithURL:url placeholderImage:nil options:0 progress:^(NSInteger receivedSize, NSInteger expectedSize) { //乘1.0是為了轉(zhuǎn)換成float類型 float progress = receivedSize * 1.0 / expectedSize; NSLog(@"下載進(jìn)度 %f",progress); } completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) { NSLog(@"完成"); }];

  1. 先從本地緩存中查找請(qǐng)求的圖片,如果有先用本地圖片占位,再?gòu)姆?wù)器請(qǐng)求下載圖片
    - (void)sd_setImageWithPreviousCachedImageWithURL:(NSURL *)url placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options progress:(SDWebImageDownloaderProgressBlock)progressBlock completed:(SDWebImageCompletionBlock)completedBlock;

  2. 下載一組動(dòng)畫圖片,并自動(dòng)播放動(dòng)畫(arrayOfURLs為一組圖片的地址數(shù)組)
    - (void)sd_setAnimationImagesWithURLs:(NSArray *)arrayOfURLs;

  3. 取消當(dāng)前下載
    - (void)sd_cancelCurrentImageLoad;

  4. 取消下載一組動(dòng)畫圖片
    - (void)sd_cancelCurrentAnimationImagesLoad;

  5. 設(shè)置是否顯示活的指示器以及樣式
    注意:必須在請(qǐng)求下載圖片之前給UIImageView設(shè)置!不然無(wú)法顯示!
    - (void)setShowActivityIndicatorView:(BOOL)show;
    - (void)setIndicatorStyle:(UIActivityIndicatorViewStyle)style;


二、 UIButton的類擴(kuò)展

#import "UIButton+WebCache.h"

  1. 獲取當(dāng)前按鈕圖片的地址
    - (NSURL *)sd_currentImageURL;

  2. 獲取指定狀態(tài)下按鈕圖片地址
    - (NSURL *)sd_imageURLForState:(UIControlState)state;

  3. 設(shè)置不同UIControlState狀態(tài)下的按鈕圖片
    - (void)sd_setImageWithURL:(NSURL *)url forState:(UIControlState)state;
    - (void)sd_setImageWithURL:(NSURL *)url forState:(UIControlState)state placeholderImage:(UIImage *)placeholder;
    - (void)sd_setImageWithURL:(NSURL *)url forState:(UIControlState)state placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options;
    - (void)sd_setImageWithURL:(NSURL *)url forState:(UIControlState)state completed:(SDWebImageCompletionBlock)completedBlock;
    - (void)sd_setImageWithURL:(NSURL *)url forState:(UIControlState)state placeholderImage:(UIImage *)placeholder completed:(SDWebImageCompletionBlock)completedBlock;
    - (void)sd_setImageWithURL:(NSURL *)url forState:(UIControlState)state placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options completed:(SDWebImageCompletionBlock)completedBlock;

  4. 設(shè)置不同狀態(tài)的按鈕背景圖片
    - (void)sd_setBackgroundImageWithURL:(NSURL *)url forState:(UIControlState)state;
    - (void)sd_setBackgroundImageWithURL:(NSURL *)url forState:(UIControlState)state placeholderImage:(UIImage *)placeholder;
    - (void)sd_setBackgroundImageWithURL:(NSURL *)url forState:(UIControlState)state placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options;
    - (void)sd_setBackgroundImageWithURL:(NSURL *)url forState:(UIControlState)state completed:(SDWebImageCompletionBlock)completedBlock;
    - (void)sd_setBackgroundImageWithURL:(NSURL *)url forState:(UIControlState)state placeholderImage:(UIImage *)placeholder completed:(SDWebImageCompletionBlock)completedBlock;
    - (void)sd_setBackgroundImageWithURL:(NSURL *)url forState:(UIControlState)state placeholderImage:(UIImage *)placeholder options:(SDWebImageOptions)options completed:(SDWebImageCompletionBlock)completedBlock;

  5. 取消當(dāng)前指定狀態(tài)按鈕圖片下載
    - (void)sd_cancelImageLoadForState:(UIControlState)state;

  6. 取消當(dāng)前指定狀態(tài)按鈕背景圖片下載
    - (void)sd_cancelBackgroundImageLoadForState:(UIControlState)state;


三、參數(shù)介紹

options 枚舉:
  1. SDWebImageRetryFailed 失敗后重試, 默認(rèn)如果下載失敗,這個(gè)url會(huì)被加入黑名單并且不會(huì)嘗試再次下載,設(shè)置這個(gè)枚舉會(huì)阻止把失敗的url加入黑名單,不斷嘗試重新下載
  2. SDWebImageLowPriority 延遲下載, 默認(rèn)情況下,圖片會(huì)在交互發(fā)生的時(shí)候下載(例如你滑動(dòng)tableview的時(shí)候),這個(gè)枚舉會(huì)禁止這個(gè)特性,導(dǎo)致的結(jié)果就是在scrollview減速的時(shí)候才會(huì)開始下載(也就是你滑動(dòng)的時(shí)候scrollview不下載,你手從屏幕上移走,scrollview開始減速的時(shí)候才會(huì)開始下載圖片)
  3. SDWebImageCacheMemoryOnly 只在內(nèi)存緩存
  4. SDWebImageProgressiveDownload 漸進(jìn)式下載,顯示的圖像是逐步在下載
  5. SDWebImageRefreshCached 刷新緩存,有時(shí)本地圖片更新后與服務(wù)器沒有同步一致時(shí)可以使用(例如更新頭像),專門處理相同url,但不同image的情況的
    原因:默認(rèn)情況下,SDWebImage會(huì)忽略Header中的緩存設(shè)置,將圖片以u(píng)rl為key進(jìn)行保存,url與圖片是一一對(duì)應(yīng)關(guān)系。所以請(qǐng)求同一個(gè)url時(shí),SDWebImage會(huì)從緩存中取得圖片。一般的情況下用此方法可以滿足我們的應(yīng)用要求,但是如果你請(qǐng)求同一個(gè)url,而這張圖片在服務(wù)器端更新了,本地客戶端再次請(qǐng)求時(shí)還是會(huì)返回緩存中的舊圖片,例如加載頭像類經(jīng)常更新的圖片時(shí),就會(huì)出現(xiàn)頭像不能更新的問(wèn)題,由于url與圖片一一對(duì)應(yīng),一種解決的辦法是改變部分url地址方式實(shí)現(xiàn)更新,不過(guò)這種方法操作起來(lái)很復(fù)雜, 另一種將第三個(gè)參數(shù)設(shè)置為SDWebImageRefreshCached就可以實(shí)現(xiàn)圖片更新操作了。
  6. SDWebImageContinueInBackground 啟動(dòng)后臺(tái)下載,app進(jìn)入后臺(tái)后繼續(xù)下載
  7. SDWebImageHandleCookies 處理存儲(chǔ)在NSHTTPCookieStore中的cookie
    NSMutableURLRequest.HTTPShouldHandleCookies = YES;
  8. SDWebImageAllowInvalidSSLCertificates 允許使用無(wú)效的SSL證書,主要用于測(cè)試目的,在正式環(huán)境中慎用
  9. SDWebImageHighPriority 優(yōu)先下載
  10. SDWebImageDelayPlaceholder 等待下載完成后再顯示占位圖片,延遲顯示占位圖片
  11. SDWebImageTransformAnimatedImage 改變動(dòng)畫形象
  12. SDWebImageAvoidAutoSetImage 下載完成后手動(dòng)設(shè)置圖片,默認(rèn)是下載完成后自動(dòng)放到ImageView上
SDWebImageCompletionBlock

typedef void(^SDWebImageCompletionBlock)(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL);
參數(shù):
(1)請(qǐng)求的圖片
(2)請(qǐng)求圖片為空的錯(cuò)誤
(3) SDImageCacheType 緩存類型,下次是從網(wǎng)上獲取還是從本地獲取, 枚舉:
SDImageCacheTypeNone 永不緩存,但是從網(wǎng)上下載
SDImageCacheTypeDisk 只緩存到磁盤上
SDImageCacheTypeMemory 只緩存到內(nèi)存中
(4)圖片的網(wǎng)絡(luò)地址

SDWebImageDownloaderProgressBlock

typedef void(^SDWebImageDownloaderProgressBlock)(NSInteger receivedSize, NSInteger expectedSize);
progress 參數(shù):
receivedSize 接收到的字節(jié)數(shù)
expectedSize 期望下載的字節(jié)數(shù)
//乘1.0是為了轉(zhuǎn)換成float類型
float progress = receivedSize * 1.0 / expectedSize;


四、本地緩存

#import"SDImageCache.h"
介紹:很多時(shí)候我們可能拍照得到的一張圖片要多個(gè)地方使用,那么我們就希望可以把這張圖片放到緩存里面,然后每次用這張圖片的時(shí)候就去通過(guò)特定的方式取即可。

屬性:
  1. 是否壓縮圖片
    @property (assign, nonatomic) BOOL shouldDecompressImages;
  2. 是否禁用iCloud,默認(rèn)YES
    @property (assign, nonatomic) BOOL shouldDisableiCloud;
  3. 是否緩存到內(nèi)存,默認(rèn)YES
    @property (assign, nonatomic) BOOL shouldCacheImagesInMemory;
  4. 最大緩存成本,針對(duì)內(nèi)存
    @property (assign, nonatomic) NSUInteger maxMemoryCost;
  5. 最大緩存?zhèn)€數(shù),針對(duì)內(nèi)存
    @property (assign, nonatomic) NSUInteger maxMemoryCountLimit;
  6. 最大緩存時(shí)間,單位:秒,針對(duì)磁盤緩存,默認(rèn)是一周,自動(dòng)把一星期以前緩存的圖片刪除掉
    @property (assign, nonatomic) NSInteger maxCacheAge;
  7. 最大緩存大小,單位字節(jié),針對(duì)磁盤,默認(rèn)無(wú)限制0,需要自己設(shè)置
    @property (assign, nonatomic) NSUInteger maxCacheSize;
方法:
1、獲取緩存單例對(duì)象

+ (SDImageCache *)sharedImageCache;

2、創(chuàng)建緩存空間
  1. 在沙盒的cache目錄下創(chuàng)建一個(gè)指定名字的緩存空間(文件夾)
    - (id)initWithNamespace:(NSString *)ns;
  2. 在磁盤指定目錄(directory)下創(chuàng)建一個(gè)指定名字的緩存空間
    - (id)initWithNamespace:(NSString *)ns diskCacheDirectory:(NSString *)directory;
  3. 添加一個(gè)只讀的緩存路徑
    - (void)addReadOnlyCachePath:(NSString *)path;
3、緩存圖片到內(nèi)存和磁盤上
  1. 往內(nèi)存和磁盤上存儲(chǔ)一個(gè)圖片(key參數(shù)是唯一的,用來(lái)取出圖片,一般是圖片的絕對(duì)路徑)
    - (void)storeImage:(UIImage *)image forKey:(NSString *)key;
    例子:
    SDImageCache *imageCache = [SDImageCache sharedImageCache]; [imageCache storeImage:image forKey:@"myphoto" toDisk:YES];
  2. 緩存一個(gè)圖片到內(nèi)存,并設(shè)置是否緩存到磁盤上
    - (void)storeImage:(UIImage *)image forKey:(NSString *)key toDisk:(BOOL)toDisk;
  3. 緩存的基礎(chǔ)方法,緩存一個(gè)圖片到內(nèi)存,并設(shè)置是否緩存到磁盤上(recalculate 是否重新計(jì)算圖片的data , imageData 圖片的data)
    - (void)storeImage:(UIImage *)image recalculateFromImage:(BOOL)recalculate imageData:(NSData *)imageData forKey:(NSString *)key toDisk:(BOOL)toDisk;
4、異步在磁盤上查找指定key圖片的緩存,完成后回調(diào)block

- (NSOperation *)queryDiskCacheForKey:(NSString *)key done:(SDWebImageQueryCompletedBlock)doneBlock;

5、從內(nèi)存、磁盤獲取指定key的圖片

- (UIImage *)imageFromMemoryCacheForKey:(NSString *)key;
- (UIImage *)imageFromDiskCacheForKey:(NSString *)key;

6、刪除指定key的圖片(fromDisk 是否刪除磁盤緩存,completion刪除結(jié)束后回調(diào)無(wú)參block)

- (void)removeImageForKey:(NSString *)key;
- (void)removeImageForKey:(NSString *)key withCompletion:(SDWebImageNoParamsBlock)completion;
- (void)removeImageForKey:(NSString *)key fromDisk:(BOOL)fromDisk;
- (void)removeImageForKey:(NSString *)key fromDisk:(BOOL)fromDisk withCompletion:(SDWebImageNoParamsBlock)completion;

7、清除所有緩存
  1. 清除所有內(nèi)存圖片緩存
    - (void)clearMemory;
  2. 清除所有磁盤緩存圖片時(shí)回調(diào)一個(gè)block
    - (void)clearDiskOnCompletion:(SDWebImageNoParamsBlock)completion;
  3. 清除所有磁盤緩存
    - (void)clearDisk;
  4. 從磁盤刪除所有過(guò)期的圖片時(shí)立即調(diào)用
    - (void)cleanDiskWithCompletionBlock:(SDWebImageNoParamsBlock)completionBlock;
  5. 刪除所有磁盤上過(guò)期的緩存圖片
    - (void)cleanDisk;
8、獲取緩存大小、緩存?zhèn)€數(shù)
  1. 獲取磁盤緩存大小
    - (NSUInteger)getSize;
  2. 獲取磁盤上緩存圖片的個(gè)數(shù)
    - (NSUInteger)getDiskCount;
  3. 異步計(jì)算磁盤緩存的大小
    - (void)calculateSizeWithCompletionBlock:(SDWebImageCalculateSizeBlock)completionBlock;
9、從磁盤查找緩存圖片
  1. 異步從磁盤中查找指定key的圖片緩存,查找完成后回調(diào)這個(gè)block(該block永遠(yuǎn)在主線程執(zhí)行)
    - (void)diskImageExistsWithKey:(NSString*)key completion:(SDWebImageCheckCacheCompletionBlock)completionBlock;
  2. 檢查磁盤中是否存在指定key的圖片緩存
    - (BOOL)diskImageExistsWithKey:(NSString *)key;
  3. 通過(guò)圖片的key獲取其緩存路徑(path:緩存路徑的根路徑)
    - (NSString*)cachePathForKey:(NSString*)key inPath:(NSString*)path;
  4. 從默認(rèn)緩存路徑下獲取指定key圖片的路徑
    - (NSString *)defaultCachePathForKey:(NSString *)key;

五、播放gif

#import "UIImage+GIF.h"

  1. 播放指定名字gif圖片
    + (UIImage *)sd_animatedGIFNamed:(NSString *)name;
  2. 用指定gif的data播放
    + (UIImage *)sd_animatedGIFWithData:(NSData *)data;
  3. 設(shè)置gif圖片尺寸
    - (UIImage *)sd_animatedImageByScalingAndCroppingToSize:(CGSize)size;

六、SDWebImage 實(shí)現(xiàn)原理

SDWebImage框架結(jié)構(gòu).png

先講下大體架構(gòu):最外層是一個(gè)SDWebImageManager單例工具類管理另外兩個(gè)單例類,一個(gè)是作下載處理的SDWebImageDownloader,它管理多個(gè)下載操作SDWebImageDownloaderOperation,一個(gè)作緩存處理的SDImageCache。

大體執(zhí)行過(guò)程:當(dāng)我們需要下載圖片時(shí),先讓SDImageCache從緩存中找,如果找不到就異步從硬盤中讀取圖片,如果讀取到就將圖片緩存到內(nèi)存并回調(diào)給SDWebImageManager,如果找不到就讓SDWebImageDownloader 執(zhí)行下載操作,在 SDWebImageDownloaderOperation 單個(gè)圖片的下載操作中利用 NSURLConnection 執(zhí)行下載,實(shí)現(xiàn)代理監(jiān)聽下載進(jìn)度等,下載完成后交給SDWebImageDecoder 圖片異步解碼,完成后回調(diào)給SDWebImageDownloader,再回調(diào)給SDWebImageManager,再讓SDImageCache去執(zhí)行內(nèi)存和磁盤(異步)的緩存操作。

具體過(guò)程:

  • UIImageView+WebCache: setImageWithURL:placeholderImage:options: 先顯示 placeholderImage ,同時(shí)由SDWebImageManager 根據(jù) URL 來(lái)在本地查找圖片。
  • SDWebImageManager: downloadWithURL:delegate:options:userInfo: SDWebImageManager是將UIImageView+WebCache同SDImageCache鏈接起來(lái)的類, SDImageCache: queryDiskCacheForKey:delegate:userInfo:用來(lái)從緩存根據(jù)CacheKey查找圖片是否已經(jīng)在緩存中
  • 如果內(nèi)存中已經(jīng)有圖片緩存, SDWebImageManager會(huì)回調(diào)SDImageCacheDelegate : imageCache:didFindImage:forKey:userInfo:
  • 而 UIImageView+WebCache 則回調(diào)SDWebImageManagerDelegate: webImageManager:didFinishWithImage:來(lái)顯示圖片。
  • 如果內(nèi)存中沒有圖片緩存,那么生成 NSInvocationOperation 添加到隊(duì)列,從硬盤查找圖片是否已被下載緩存。
  • 根據(jù) URLKey 在硬盤緩存目錄下嘗試讀取圖片文件。這一步是在 NSOperation 進(jìn)行的操作,所以回主線程進(jìn)行結(jié)果回調(diào)
    notifyDelegate:
  • 如果上一操作從硬盤讀取到了圖片,將圖片添加到內(nèi)存緩存中(如果空閑內(nèi)存過(guò)小,會(huì)先清空內(nèi)存緩存)。SDImageCacheDelegate 回調(diào) imageCache:didFindImage:forKey:userInfo:進(jìn)而回調(diào)展示圖片。
  • 如果從硬盤緩存目錄讀取不到圖片,說(shuō)明所有緩存都不存在該圖片,需要下載圖片,回調(diào)
    imageCache:didNotFindImageForKey:userInfo:
  • 共享或重新生成一個(gè)下載器 SDWebImageDownloader 開始下載圖片。
  • 圖片下載由 NSURLConnection 來(lái)做,實(shí)現(xiàn)相關(guān) delegate 來(lái)判斷圖片下載中、下載完成和下載失敗。
  • connection:didReceiveData: 中利用 ImageIO 做了按圖片下載進(jìn)度加載效果。
  • connectionDidFinishLoading: 數(shù)據(jù)下載完成后交給 SDWebImageDecoder 做圖片解碼處理。
  • 圖片解碼處理在一個(gè) NSOperationQueue 完成,不會(huì)拖慢主線程 UI。如果有需要對(duì)下載的圖片進(jìn)行二次處理,最好也在這里完成,效率會(huì)好很多。
  • 在主線程 notifyDelegateOnMainThreadWithInfo: 宣告解碼完成,imageDecoder:didFinishDecodingImage:userInfo: 回調(diào)給 SDWebImageDownloader。
  • imageDownloader:didFinishWithImage: 回調(diào)給 SDWebImageManager 告知圖片下載完成。
  • 通知所有的 downloadDelegates 下載完成,回調(diào)給需要的地方展示圖片。
  • 將圖片保存到 SDImageCache 中,內(nèi)存緩存和硬盤緩存同時(shí)保存。
  • 寫文件到硬盤在單獨(dú) NSInvocationOperation 中完成,避免拖慢主線程。
  • 如果是在iOS上運(yùn)行,SDImageCache 在初始化的時(shí)候會(huì)注冊(cè)notification 到 UIApplicationDidReceiveMemoryWarningNotification 以及 UIApplicationWillTerminateNotification,在內(nèi)存警告的時(shí)候清理內(nèi)存圖片緩存,應(yīng)用結(jié)束的時(shí)候清理過(guò)期圖片。
  • SDWebImagePrefetcher 可以預(yù)先下載圖片,方便后續(xù)使用。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,488評(píng)論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,034評(píng)論 3 414
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,327評(píng)論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,554評(píng)論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,337評(píng)論 6 404
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 54,883評(píng)論 1 321
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,975評(píng)論 3 439
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,114評(píng)論 0 286
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,625評(píng)論 1 332
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,555評(píng)論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,737評(píng)論 1 369
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,244評(píng)論 5 355
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 43,973評(píng)論 3 345
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,362評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,615評(píng)論 1 280
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,343評(píng)論 3 390
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,699評(píng)論 2 370

推薦閱讀更多精彩內(nèi)容