UITableView優(yōu)化方法

  1. UITableView的簡單認(rèn)識

UITableView最核心的思想就是UITableViewCell的重用機制。簡單的理解就是:UITableView只會創(chuàng)建一屏幕(或一屏幕多一點)的UITableViewCell,其他都是從中取出來重用的。每當(dāng)Cell滑出屏幕時,就會放入到一個集合(或數(shù)組)中(這里就相當(dāng)于一個重用池),當(dāng)要顯示某一位置的Cell時,會先去集合(或數(shù)組)中取,如果有,就直接拿來顯示;如果沒有,才會創(chuàng)建。這樣做的好處可想而知,極大的減少了內(nèi)存的開銷。

知道UITableViewCell的重用原理后,我們來看看UITableView的回調(diào)方法。UITableView最主要的兩個回調(diào)方法是tableView:cellForRowAtIndexPath:和tableView:heightForRowAtIndexPath:。理想上我們是會認(rèn)為UITableView會先調(diào)用前者,再調(diào)用后者,因為這和我們創(chuàng)建控件的思路是一樣的,先創(chuàng)建它,再設(shè)置它的布局。但實際上卻并非如此,我們都知道,UITableView是繼承自UIScrollView的,需要先確定它的contentSize及每個Cell的位置,然后才會把重用的Cell放置到對應(yīng)的位置。所以事實上,UITableView的回調(diào)順序是先多次調(diào)用tableView:heightForRowAtIndexPath:以確定contentSize及Cell的位置,然后才會調(diào)用tableView:cellForRowAtIndexPath:,從而來顯示在當(dāng)前屏幕的Cell。

舉個例子來說:如果現(xiàn)在要顯示100個Cell,當(dāng)前屏幕顯示5個。那么刷新(reload)UITableView時,UITableView會先調(diào)用100次tableView:heightForRowAtIndexPath:方法,然后調(diào)用5次tableView:cellForRowAtIndexPath:方法;滾動屏幕時,每當(dāng)Cell滾入屏幕,都會調(diào)用一次tableView:heightForRowAtIndexPath:、tableView:cellForRowAtIndexPath:方法。

看到這里,想必大伙也都能隱約察覺到,UITableView優(yōu)化的首要任務(wù)是要優(yōu)化上面兩個回調(diào)方法。事實也確實如此,下面按照我探討進(jìn)階的過程,來研究如何優(yōu)化:

優(yōu)化探索,項目拿到手時代碼是這樣:

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

    ContacterTableCell *cell = [tableView dequeueReusableCellWithIdentifier:@"ContacterTableCell"];

    if (!cell) {

        cell = (ContacterTableCell *)[[[NSBundle mainBundle] loadNibNamed:@"ContacterTableCell" owner:self options:nil] lastObject];

    }

    NSDictionary *dict = self.dataList[indexPath.row];

    [cell setContentInfo:dict];

    return cell;

}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {

    UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];

    return cell.frame.size.height;

} ```
看到這段代碼,對于剛畢業(yè)的我來說,覺得還是蠻巧妙的,但巧歸巧,當(dāng)Cell非常復(fù)雜的時候,直接卡出翔了。。。特別是在我的Touch4上,這我能忍?!好吧,依據(jù)上面UITableView原理的分析,我們先來分析它為什么卡?

這樣寫,在Cell賦值內(nèi)容的時候,會根據(jù)內(nèi)容設(shè)置布局,當(dāng)然也就可以知道Cell的高度,想想如果1000行,那就會調(diào)用1000+頁面Cell個數(shù)次tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath方法,而我們對Cell的處理操作,都是在這個方法里的!什么賦值、布局等等。開銷自然很大,這種方案Pass。。。改進(jìn)代碼。

改進(jìn)代碼后:
  • (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {

    NSDictionary *dict = self.dataList[indexPath.row];

    return [ContacterTableCell cellHeightOfInfo:dict];

} ```
思路是把賦值和計算布局分離。這樣讓tableView:cellForRowAtIndexPath:方法只負(fù)責(zé)賦值,tableView:heightForRowAtIndexPath:方法只負(fù)責(zé)計算高度。注意:兩個方法盡可能的各司其職,不要重疊代碼!兩者都需要盡可能的簡單易算。Run一下,會發(fā)現(xiàn)UITableView滾動流暢了很多。。。

基于上面的實現(xiàn)思路,我們可以在獲得數(shù)據(jù)后,直接先根據(jù)數(shù)據(jù)源計算出對應(yīng)的布局,并緩存到數(shù)據(jù)源中,這樣在tableView:heightForRowAtIndexPath:方法中就直接返回高度,而不需要每次都計算了。

用 “空間換時間”
將計算行高的時間提前到從服務(wù)器摟回數(shù)據(jù)的時候,計算完了高度一并寫回數(shù)據(jù)庫,

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {

    NSDictionary *dict = self.dataList[indexPath.row];

CGRect rect = [dict[@"frame"] CGRectValue];

    return rect.frame.height;

} ```
其實上面的改進(jìn)方法并不是最佳方案,但基本能滿足簡單的界面!記得開頭我的任務(wù)嗎?像朋友圈那樣的圖文混排,這種方案還是扛不住的!我們需要進(jìn)入更深層次的探究:自定義Cell的繪制。

我們在Cell上添加系統(tǒng)控件的時候,實質(zhì)上系統(tǒng)都需要調(diào)用底層的接口進(jìn)行繪制,當(dāng)我們大量添加控件時,對資源的開銷也會很大,所以我們可以索性直接繪制,提高效率。是不是說的很抽象?廢話不多說,直接上代碼:

首先需要給自定義的Cell添加draw方法,(當(dāng)然也可以重寫drawRect)然后在方法體中實現(xiàn):

//異步繪制

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

    CGRect rect = [_data[@"frame"] CGRectValue];

    UIGraphicsBeginImageContextWithOptions(rect.size, YES, 0);

    CGContextRef context = UIGraphicsGetCurrentContext();

//整個內(nèi)容的背景

    [[UIColor colorWithRed:250/255.0 green:250/255.0 blue:250/255.0 alpha:1] set];

    CGContextFillRect(context, rect);

//轉(zhuǎn)發(fā)內(nèi)容的背景

    if ([_data valueForKey:@"subData"]) {

        [[UIColor colorWithRed:243/255.0 green:243/255.0 blue:243/255.0 alpha:1] set];

        CGRect subFrame = [_data[@"subData"][@"frame"] CGRectValue];

        CGContextFillRect(context, subFrame);

        [[UIColor colorWithRed:200/255.0 green:200/255.0 blue:200/255.0 alpha:1] set];

        CGContextFillRect(context, CGRectMake(0, subFrame.origin.y, rect.size.width, .5));

    }

     

    {

//名字

        float leftX = SIZE_GAP_LEFT+SIZE_AVATAR+SIZE_GAP_BIG;

        float x = leftX;

        float y = (SIZE_AVATAR-(SIZE_FONT_NAME+SIZE_FONT_SUBTITLE+6))/2-2+SIZE_GAP_TOP+SIZE_GAP_SMALL-5;

        [_data[@"name"] drawInContext:context withPosition:CGPointMake(x, y) andFont:FontWithSize(SIZE_FONT_NAME)

                         andTextColor:[UIColor colorWithRed:106/255.0 green:140/255.0 blue:181/255.0 alpha:1]

                            andHeight:rect.size.height];

//時間+設(shè)備

        y += SIZE_FONT_NAME+5;

        float fromX = leftX;

        float size = [UIScreen screenWidth]-leftX;

        NSString *from = [NSString stringWithFormat:@"%@  %@", _data[@"time"], _data[@"from"]];

        [from drawInContext:context withPosition:CGPointMake(fromX, y) andFont:FontWithSize(SIZE_FONT_SUBTITLE)

               andTextColor:[UIColor colorWithRed:178/255.0 green:178/255.0 blue:178/255.0 alpha:1]

                  andHeight:rect.size.height andWidth:size];

    }

//將繪制的內(nèi)容以圖片的形式返回,并調(diào)主線程顯示

UIImage *temp = UIGraphicsGetImageFromCurrentImageContext();

    UIGraphicsEndImageContext();

    dispatch_async(dispatch_get_main_queue(), ^{

        if (flag==drawColorFlag) {

            postBGView.frame = rect;

            postBGView.image = nil;

            postBGView.image = temp;

        }

}

//內(nèi)容如果是圖文混排,就添加View,用CoreText繪制

[self drawText];

}}
上述代碼只貼出來部分功能,但大體的思路都是一樣的,各個信息都是根據(jù)之前算好的布局進(jìn)行繪制的。這里是需要異步繪制,但如果在重寫drawRect方法就不需要用GCD異步線程了,因為drawRect本來就是異步繪制的。對于圖文混排的繪制,可以移步Google,研究下CoreText,這塊內(nèi)容太多了,不便展開。

好了,至此,我們又讓UITableView的效率提高了一個等級!但我們的步伐還遠(yuǎn)遠(yuǎn)不止這些,下面我們還可以從UIScrollView的角度出發(fā),再次找到突破口。

滑動UITableView時,按需加載對應(yīng)的內(nèi)容

直接上代碼:

//按需加載 - 如果目標(biāo)行與當(dāng)前行相差超過指定行數(shù),只在目標(biāo)滾動范圍的前后指定3行加載。

  • (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset{

    NSIndexPath *ip = [self indexPathForRowAtPoint:CGPointMake(0, targetContentOffset->y)];

    NSIndexPath *cip = [[self indexPathsForVisibleRows] firstObject];

    NSInteger skipCount = 8;

    if (labs(cip.row-ip.row)>skipCount) {

      NSArray *temp = [self indexPathsForRowsInRect:CGRectMake(0, targetContentOffset->y, self.width, self.height)];
    
      NSMutableArray *arr = [NSMutableArray arrayWithArray:temp];
    
      if (velocity.y<0) {
    
          NSIndexPath *indexPath = [temp lastObject];
    
          if (indexPath.row+33) {
    
              [arr addObject:[NSIndexPath indexPathForRow:indexPath.row-3 inSection:0]];
    
              [arr addObject:[NSIndexPath indexPathForRow:indexPath.row-2 inSection:0]];
    
              [arr addObject:[NSIndexPath indexPathForRow:indexPath.row-1 inSection:0]];
    
          }
    
      }
    
      [needLoadArr addObjectsFromArray:arr];
    

    }

}
記得在tableView:cellForRowAtIndexPath:方法中加入判斷:

if (needLoadArr.count>0&&[needLoadArr indexOfObject:indexPath]==NSNotFound) {

[cell clear];

return;

} ```
滾動很快時,只加載目標(biāo)范圍內(nèi)的Cell,這樣按需加載,極大的提高流暢度。

寫了這么多,也差不多該來個總結(jié)了!UITableView的優(yōu)化主要從三個方面入手:

提前計算并緩存好高度(布局),因為heightForRowAtIndexPath:是調(diào)用最頻繁的方法;
異步繪制,遇到復(fù)雜界面,遇到性能瓶頸時,可能就是突破口;
滑動時按需加載,這個在大量圖片展示,網(wǎng)絡(luò)加載的時候很管用!(SDWebImage已經(jīng)實現(xiàn)異步加載,配合這條性能杠杠的)。
除了上面最主要的三個方面外,還有很多幾乎大伙都很熟知的優(yōu)化點:

正確使用reuseIdentifier來重用Cells
盡量使所有的view opaque,包括Cell自身
盡量少用或不用透明圖層
如果Cell內(nèi)現(xiàn)實的內(nèi)容來自web,使用異步加載,緩存請求結(jié)果
減少subviews的數(shù)量
在heightForRowAtIndexPath:中盡量不使用cellForRowAtIndexPath:,如果你需要用到它,只用一次然后緩存結(jié)果
盡量少用addView給Cell動態(tài)添加View,可以初始化時就添加,然后通過hide來控制是否顯示

  1. 那么在cell里面異步加載圖片是個程序員都會想到,但是如果你給每個循環(huán)對象都加上異步加載,并且下滑的時候,這一操作將會被執(zhí)行,雖然是異步,但是一個app里面的線程過多也會卡頓的,特別是在下滑操作的時候給每個圖片進(jìn)行異步加載

那么這里可以利用UIScrollViewDelegate代理很好的解決這問題

  • (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
  • (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
    可以識別tableview禁止或者減速滑動結(jié)束的時候進(jìn)行異步加載圖片
    以下方法來執(zhí)行異步加載操作
    //獲取可見部分的對象
    NSArray *visiblePaths = [self.tableView indexPathsForVisibleRows];
    for (NSIndexPath *indexPath in visiblePaths)
    {
    //獲取的dataSource里面的對象,并且判斷加載完成的不需要再次異步加載
    <code>
    }
    同時在cell繪制中也做限制
  • (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    if (self.tableView.dragging == NO && self.tableView.decelerating == NO)
    {
    //開始異步加載圖片
    <code>
    }
    如果tableview 停止滑動的時候開始異步加載圖片
    最后也別忘記在內(nèi)存緊張的情況下釋放調(diào)所有的異步線程,以保證的你的app不會被系統(tǒng)強制關(guān)閉
  • (void)didReceiveMemoryWarning{
    // 釋放調(diào)異步加載圖片的線程以及所有圖片資源對象
    <code>
    }
  1. 自定義view
    UITableViewCell包含了textLabel、detailTextLabel和imageView等view,而你還可以自定義一些視圖放在它的contentView里。然而view是很大的對象,創(chuàng)建它會消耗較多資源,并且也影響渲染的性能。

如果你的table cell包含圖片,且數(shù)目較多,使用默認(rèn)的UITableViewCell會非常影響性能。奇怪的是,使用自定義的view,而非預(yù)定義的view,明顯會快些。

當(dāng)然,最佳的解決辦法還是繼承UITableViewCell,并在其drawRect:中自行繪制:

 1     - (void)drawRect:(CGRect)rect
 2     {
 3         if (image)
 4         {
 5             [image drawAtPoint:imagePoint];
 6             self.image = nil;
 7         } else {
 8             [placeHolder drawAtPoint:imagePoint];
 9         }
10         [text drawInRect:textRect withFont:font lineBreakMode:UILineBreakModeTailTruncation];
11     } ```
不過這樣一來,你會發(fā)現(xiàn)選中一行后,這個cell就變藍(lán)了,其中的內(nèi)容就被擋住了。最簡單的方法就是將cell的selectionStyle屬性設(shè)為UITableViewCellSelectionStyleNone,這樣就不會被高亮了。 

此 外還可以創(chuàng)建CALayer,將內(nèi)容繪制到layer上,然后對cell的contentView.layer調(diào)用addSublayer:方法。這個例 子中,layer并不會顯著影響性能,但如果layer透明,或者有圓角、變形等效果,就會影響到繪制速度了。解決辦法可參見后面的預(yù)渲染圖像。 

不要做多余的繪制工作。

在實現(xiàn)drawRect:的時候,它的rect參數(shù)就是需要繪制的區(qū)域,這個區(qū)域之外的不需要進(jìn)行繪制。

例如上例中,就可以用CGRectIntersectsRect、CGRectIntersection或CGRectContainsRect判斷是否需要繪制image和text,然后再調(diào)用繪制方法。

預(yù)渲染圖像。

你會發(fā)現(xiàn)即使做到了上述幾點,當(dāng)新的圖像出現(xiàn)時,仍然會有短暫的停頓現(xiàn)象。解決的辦法就是在bitmap context里先將其畫一遍,導(dǎo)出成UIImage對象,然后再繪制到屏幕,詳細(xì)做法可見《利用預(yù)渲染加速iOS設(shè)備的圖像顯示》。可以節(jié)省每次圖片的解壓縮和重采樣的時間。

參考url:https://www.keakon.NET/2011/07/26/利用預(yù)渲染加速iOS設(shè)備的圖像顯示。

此外,自動載入更新數(shù)據(jù)對用戶來說也很友好,這減少了用戶等待下載的時間。例如每次載入50條信息,那就可以在滾動到倒數(shù)第10條以內(nèi)時,加載更多信息:

``` - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath 
{ if (count - indexPath.row < 10 && !updating) { updating = YES; [self update]; } 
}// update方法獲取到結(jié)果后,設(shè)置updating為NO  ```


4. 圖片尺寸處理

圖片異步加載無非就是在這個方法里發(fā)起異步請求,圖片加載完后根據(jù) UIImageView 的引用設(shè)置圖片。有經(jīng)驗的程序員可能會使用 懶加載 的方式減少快速滑動時因為網(wǎng)絡(luò)請求過于頻繁與切換線程顯示圖片造成的卡頓。這里還有個問題,拿回來的圖片一定和最后顯示的大小不一樣,有時候偷懶,直接設(shè)置 image view 的 contentMode 屬性要 image view 自己 壓縮。這是一個很取巧的方法,但是對 table view 的滾動速度也會造成 不容忽視 的影響。對圖片變形需要對圖片做 transform ,每次壓縮圖片都要對圖片乘以一個變換矩陣,如果你的圖片很多,這個計算量是不同忽視的。
 
優(yōu)化建議:從網(wǎng)絡(luò)摟回來圖片后先根據(jù)需要顯示的圖片大小切成合適大小的圖,每次只顯示處理過大小的圖片,當(dāng)查看大圖時在顯示大圖。如果服務(wù)器能直接返回預(yù)處理好的小圖和圖片的大小更好。

洋紅色是因為像素沒對齊,比如上面的 label,一般情況下因為像素沒對齊,需要抗鋸齒,圖像會出現(xiàn)模糊的現(xiàn)象。
解決辦法:在設(shè)置 view 的 frame 時,在高分屏避免出現(xiàn) 21.3,6.7這樣的小數(shù),尤其是 x,y坐標(biāo),用 ceil 或 floor 或 round 取整。每 0.5 個點對應(yīng)一個 pixel,0.3,0.7這樣的就難為 iPhone 了,低分屏不要出現(xiàn)小數(shù)。
 
黃色是因為顯示的圖片實際大小與顯示大小不同,對圖片進(jìn)行了拉伸,測試顯示使用 image view 顯示實際大小的圖也會變黃。
減少洋紅色和黃色可以提升滾動的流暢性
 
手動 Drawing 視圖提升流暢性
 
如果通過上面的方法,滾動速度還不能達(dá)到可以容忍的速度,那就只剩下最后一個辦法了,手動繪制視圖。
 
手動繪制方法,不是直接子類化 UITableViewCell,然后覆蓋 drawRect: 方法,這樣你會得到一個大黑塊!因為 cell 中不是只有一個 content view。如果不了解 cell 的層次結(jié)構(gòu),可以用 Reveal 去看下。
 
繪制 cell 不建議使用 UIView,建議使用 CALayer。 UIView 的繪制是建立在 CoreGraphic 上的,使用的是 CPU。CALayer 使用的是 Core Animation,CPU,GPU 通吃,由系統(tǒng)決定使用哪個。View的繪制使用的是自下向上的一層一層的繪制,然后渲染。Layer處理的是 Texure,利用 GPU 的 Texture Cache 和獨立的浮點數(shù)計算單元加速 紋理 的處理。
 
GPU 不喜歡 透明,所以所有的繪圖一定要弄成不透明,對于圓角和陰影這些的可以截個偽透明的小圖然后繪制上去。在layer的回調(diào)里一定也只做繪圖,不做計算!

5. 預(yù)加載數(shù)據(jù)

此外,自動載入更新數(shù)據(jù)對用戶來說也很友好,這減少了用戶等待下載的時間。例如每次載入50條信息,那就可以在滾動到倒數(shù)第10條以內(nèi)時,加載更多信息:
  • (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
    if (count - indexPath.row <10 && !updating) {
    updating = YES;
    [self update];
    }
    }
    // update方法獲取到結(jié)果后,設(shè)置updating為NO
    還有一點要注意的就是當(dāng)圖片下載完成后,如果cell是可見的,還需要更新圖像:
    NSArray *indexPaths = [self.tableView indexPathsForVisibleRows];
    for (NSIndexPath *visibleIndexPathin indexPaths) {
    if (indexPath == visibleIndexPath) {
    MyTableViewCell *cell = (MyTableViewCell *)[self.tableView cellForRowAtIndexPath:indexPath];
    cell.image = image;
    [cell setNeedsDisplayInRect:imageRect];
    break;
    }
    }

源url:

http://www.cocoachina.com/ios/20150602/11968.html

http://bbs.51cto.com/thread-1123666-1-1.html

http://www.mamicode.com/info-detail-1125512.html



http://blog.csdn.Net/chengwuli125/article/details/9926959
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,527評論 6 544
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,687評論 3 429
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,640評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,957評論 1 318
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 72,682評論 6 413
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 56,011評論 1 329
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,009評論 3 449
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 43,183評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,714評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 41,435評論 3 359
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,665評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,148評論 5 365
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,838評論 3 350
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,251評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,588評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,379評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 48,627評論 2 380

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