TableView優(yōu)化之快速滑動(dòng)下的忽略加載

TableView優(yōu)化之快速滑動(dòng)下的忽略加載

系列文章:


最近在搞什么,所以就順手寫(xiě)點(diǎn)什么咯~

這兩天一直在搞一個(gè)TableView的工具類舰蟆,因?yàn)橛X(jué)得這個(gè)東西寫(xiě)完可以一勞永逸乒疏,所以就去搞了一下陕习,主要是有助于TableView的快捷開(kāi)發(fā)钦勘。沒(méi)什么好廢話的了淀散,直接說(shuō)事吧=氧卧。=

在今天的博客中你可能會(huì)看到:

  • VVeboTableView中Cell加載邏輯的解析
  • TableView代碼解耦的基本思路

恩桃笙,東西不多,一點(diǎn)一點(diǎn)說(shuō)~


VVeboTableView

其實(shí)這是VVebo項(xiàng)目中作者分享剝離的一個(gè)Demo沙绝,來(lái)告訴我們他是怎么優(yōu)化TableView的流暢性的搏明。

那么VVebo是什么呢?看名字你就猜吧闪檬,像不像微博星著,是的,它就是一款新浪微博的第三方客戶端粗悯,當(dāng)年還是有很多人追捧的虚循,不過(guò)后來(lái)新浪逐漸收回開(kāi)發(fā)接口導(dǎo)致很多功能無(wú)法實(shí)現(xiàn)就把VVebo給坑了。

那么為什么VVebo使用率那么高呢样傍?一方面是當(dāng)時(shí)新浪微博客戶端的確不行横缔,另一方面VVebo簡(jiǎn)約的風(fēng)格和流暢的體驗(yàn)俘獲了一大批用戶。所以今天我們就來(lái)探究一下他是如何做到TableView的絲滑體驗(yàn)的衫哥。

首先你可以在這里現(xiàn)在一份源碼茎刚,畢竟源碼面前沒(méi)有秘密。

在老司機(jī)看來(lái)撤逢,作者最有效的優(yōu)化分為4部分:

  • TableViewCell圓角優(yōu)化
  • 緩存行高
  • 相對(duì)固定的圖片及文字采用CoreText繪制
  • TableView加載數(shù)據(jù)邏輯優(yōu)化

1.圓角

這部分作者的優(yōu)化很簡(jiǎn)單膛锭,他沒(méi)有畫(huà)圓角!圓角是TableViewCell的幀率殺手大家都知道吧蚊荣,所以人家根本就沒(méi)有畫(huà)圓角初狰。他是怎么做的呢?覆蓋了與背景色同色的圓角圖片妇押,簡(jiǎn)單粗暴跷究,果然是個(gè)心機(jī)boy。

不過(guò)關(guān)于圓角的優(yōu)化敲霍,還是有更好的解決辦法的俊马,在這里丁存。不想看的話我給你總結(jié)一下,就兩點(diǎn):

  • 別冤枉cornerRadius柴我,問(wèn)題不在它解寝。而在于maskToBounds。普通的UIView繪制圓角時(shí)并不需要maskToBounds屬性艘儒。也就是普通的視圖圓角對(duì)卡頓沒(méi)有影響聋伦。
  • 既然有普通就有特殊:UIImageView和UILabel以及我還沒(méi)有發(fā)現(xiàn)的=。=對(duì)于UIImage的處理建議先借助CoreGraphic處理圖片吧界睁,直接繪制一個(gè)帶圓角的圖片給ImageView吧觉增。對(duì)于Label沒(méi)有太好的優(yōu)化方案,是在不行只能CoreText了翻斟。其實(shí)你會(huì)發(fā)現(xiàn)逾礁,UILable這個(gè)控件對(duì)中文十!分访惜!不嘹履!友!好债热!很多細(xì)節(jié)上中文跟英文或者字符會(huì)有很大的差異砾嫉,但是你有不能不用他,好氣哦=窒篱。=

2.緩存行高

這部分內(nèi)容老司機(jī)在上一期講述過(guò)不定高cell行高緩存的必要性及緩存的方法焕刮,這里不再贅述。


3.CoreText繪制文本

首先舌剂,復(fù)雜的層級(jí)關(guān)系同樣會(huì)給cell在繪制時(shí)添加很大的負(fù)擔(dān)济锄,這點(diǎn)是毋庸置疑的,所以VVebo的作者選擇了將一些相對(duì)重復(fù)性很大的視圖選擇使用CoreText和CoreGraphic技術(shù)直接繪制在一個(gè)視圖上霍转,這樣就減少了視圖的層級(jí)荐绝,為流暢性又添了一份可能。CoreText繪制文本的和圖片的技術(shù)你可以在老司機(jī)的CoreText實(shí)現(xiàn)圖文混排系列中得到詳細(xì)的實(shí)現(xiàn)方法避消,想看的去看吧低滩。


4.TableView加載數(shù)據(jù)邏輯優(yōu)化

到現(xiàn)在為止終于要講點(diǎn)之前沒(méi)有說(shuō)過(guò)的了=。=

說(shuō)以下主體思路岩喷,VVebo的作者認(rèn)為恕沫,當(dāng)用戶快速滑動(dòng)的時(shí)候,事實(shí)上他對(duì)滑動(dòng)過(guò)程中的內(nèi)容是不關(guān)心的纱意,他只關(guān)心滾動(dòng)結(jié)束處的內(nèi)容婶溯,那么用戶不關(guān)心的內(nèi)容她就選擇了不加載。

這是他的主體思路,來(lái)看下這部分的實(shí)現(xiàn)代碼:

- (void)drawCell:(VVeboTableViewCell *)cell withIndexPath:(NSIndexPath *)indexPath{
    NSDictionary *data = [datas objectAtIndex:indexPath.row];
    cell.selectionStyle = UITableViewCellSelectionStyleNone;
    //清除cell內(nèi)容迄委,解決復(fù)用問(wèn)題
    [cell clear];
    cell.data = data;
  //判斷如果needLoadArr中含有需要加載的indexPath而當(dāng)前indexPath又不在其中的時(shí)候褐筛,則不繪制cell直接返回
    if (needLoadArr.count>0&&[needLoadArr indexOfObject:indexPath]==NSNotFound) {
        [cell clear];
        return;
    }
  //判斷如果scrollToToping為真的時(shí)候(及點(diǎn)擊狀態(tài)欄快速回到TableView頂部的時(shí)候)不繪制cell
    if (scrollToToping) {
        return;
    }
    //上面都沒(méi)問(wèn)題的話,繪制cell
    [cell draw];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
    VVeboTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell"];
    if (cell==nil) {
        cell = [[VVeboTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
                                         reuseIdentifier:@"cell"];
    }
    [self drawCell:cell withIndexPath:indexPath];
    return cell;
}

- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView{
    [needLoadArr removeAllObjects];
}

//按需加載 - 如果目標(biāo)行與當(dāng)前行相差超過(guò)指定行數(shù)叙身,只在目標(biāo)滾動(dòng)范圍的前后指定3行加載渔扎。
- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset{
//取出滾動(dòng)停止時(shí)展示的第一個(gè)cell的indexPath
    NSIndexPath *ip = [self indexPathForRowAtPoint:CGPointMake(0, targetContentOffset->y)];
//取出當(dāng)前展示的第一個(gè)cell的indexPath
    NSIndexPath *cip = [[self indexPathsForVisibleRows] firstObject];
    NSInteger skipCount = 8;
//如果兩者之間差距很大則認(rèn)為滑動(dòng)速度很快,中間用戶都不關(guān)心信轿,直接把滾動(dòng)停止時(shí)的展示的cell加入到needLoadArr數(shù)組中
    if (labs(cip.row-ip.row)>skipCount) {
        NSArray *temp = [self indexPathsForRowsInRect:CGRectMake(0, targetContentOffset->y, self.width, self.height)];
        NSMutableArray *arr = [NSMutableArray arrayWithArray:temp];
//根據(jù)滾動(dòng)方向在前或后額外添加三個(gè)需要展示的cell晃痴,這樣看起來(lái)好像更加平滑的樣子
        if (velocity.y<0) {
            NSIndexPath *indexPath = [temp lastObject];
            if (indexPath.row+3<datas.count) {
                [arr addObject:[NSIndexPath indexPathForRow:indexPath.row+1 inSection:0]];
                [arr addObject:[NSIndexPath indexPathForRow:indexPath.row+2 inSection:0]];
                [arr addObject:[NSIndexPath indexPathForRow:indexPath.row+3 inSection:0]];
            }
        } else {
            NSIndexPath *indexPath = [temp firstObject];
            if (indexPath.row>3) {
                [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];
    }
}

- (BOOL)scrollViewShouldScrollToTop:(UIScrollView *)scrollView{
    scrollToToping = YES;
    return YES;
}

- (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView{
    scrollToToping = NO;
    [self loadContent];
}

- (void)scrollViewDidScrollToTop:(UIScrollView *)scrollView{
    scrollToToping = NO;
    [self loadContent];
}

//用戶觸摸時(shí)第一時(shí)間加載內(nèi)容
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event{
    if (!scrollToToping) {
        [needLoadArr removeAllObjects];
        [self loadContent];
    }
    return [super hitTest:point withEvent:event];
}

- (void)loadContent{
    if (scrollToToping) {
        return;
    }
    if (self.indexPathsForVisibleRows.count<=0) {
        return;
    }
    if (self.visibleCells&&self.visibleCells.count>0) {
        for (id temp in [self.visibleCells copy]) {
            VVeboTableViewCell *cell = (VVeboTableViewCell *)temp;
            [cell draw];
        }
    }
}

其實(shí)是就100行代碼,思路還是很清晰明了的财忽。作者主要是通過(guò)
-drawCell:withIndexPath:這個(gè)方法來(lái)控制cell的繪制行為的倘核。我們看看他做了什么?

首先他cell調(diào)用了clear方法即彪,這是VVeboTableViewCell中作者自己實(shí)現(xiàn)的方法笤虫,用于清除cell上面展示的內(nèi)容,這樣可以避免因cell重用而導(dǎo)致沒(méi)有繪制的cell會(huì)顯示之前的內(nèi)容的問(wèn)題祖凫。然后是判斷needLoadArr中是否包含有當(dāng)前indexPath,若沒(méi)有返回酬凳。繼續(xù)判斷當(dāng)前TableView是否處于快速回到頂部的過(guò)程中惠况,如果是的話也不繪制。最后上述條件都滿足的時(shí)候再進(jìn)行cell的繪制宁仔。

所以重點(diǎn)來(lái)了稠屠,needLoadArr什么時(shí)候添加的元素?如何獲取到TableView快速回到頂部的時(shí)間點(diǎn)翎苫?

第二點(diǎn)好說(shuō)权埠,點(diǎn)擊狀態(tài)欄的時(shí)候,TableView會(huì)詢問(wèn)代理 - scrollViewShouldScrollToTop:只有返回YES的時(shí)候才會(huì)快速回到頂部煎谍,這時(shí)我們可以在這捕獲到這個(gè)狀態(tài)攘蔽。但是可以看到作者并沒(méi)有在這選擇添加頂部可能要展示的cell進(jìn)needLoadArr數(shù)組,那么當(dāng)他滾動(dòng)到頂部的時(shí)候我們要將頂部的cell進(jìn)行直接更新呐粘,所以通過(guò)- scrollViewDidEndScrollingAnimation:- scrollViewShouldScrollToTop:兩個(gè)代理拿到到達(dá)頂部的狀態(tài)后直接更新當(dāng)前cell满俗。

回過(guò)頭來(lái)我們說(shuō)下第一點(diǎn),needLoadArr是怎么操作呢作岖?
我們知道我們是要判斷TableView快速滑動(dòng)唆垃,那我們?cè)趺茨玫竭@個(gè)行為呢?要知道沒(méi)有什么代理是直接反應(yīng)滾動(dòng)速度的痘儡,這里作者很取巧的用到了-scrollViewWillEndDragging:withVelocity:targetContentOffset:這個(gè)代理辕万。
這個(gè)代理在手指即將結(jié)束拖動(dòng)的時(shí)候出發(fā),他會(huì)告訴外界當(dāng)前的速度及這次會(huì)滾動(dòng)到的位置。

所以作者在這里判斷了目標(biāo)位置與當(dāng)前位置相差間隔渐尿,如果很大的話則認(rèn)為中間內(nèi)容不需加載醉途,直接添加目標(biāo)位置的內(nèi)容進(jìn)入數(shù)組。

恩涡戳,以上就是VVebo作者對(duì)數(shù)據(jù)加載邏輯的優(yōu)化结蟋。

這是依靠著上述四點(diǎn),VVebo才獲得了完美的滑動(dòng)體驗(yàn)渔彰,其思路也是我們開(kāi)發(fā)中可以學(xué)習(xí)和借鑒的嵌屎。


TableView解耦

這部分內(nèi)容也不是什么新鮮事,也是比較靠譜的一個(gè)思路恍涂。當(dāng)然了這部分內(nèi)容不是對(duì)性能的優(yōu)化宝惰,而是對(duì)代碼的優(yōu)化。

天天寫(xiě)TableView里面的代理是不是很煩人啊再沧,千篇一律又不能不寫(xiě)尼夺。所以想一個(gè)方法只寫(xiě)一次以后拿來(lái)直接用吧=。=

效果圖
真機(jī)不卡炒瘸!真機(jī)不卡淤堵!真機(jī)不卡!重要的事情說(shuō)三遍

放一個(gè)效果圖顷扩,老司機(jī)寫(xiě)的控制器里面看不到任何一個(gè)TableView代理然而還是能正常顯示并實(shí)現(xiàn)很多功能拐邪。

但是代碼怎么可能不寫(xiě),只是我在別的地方寫(xiě)過(guò)了隘截,并且花了大把時(shí)間進(jìn)行解耦扎阶,讓每一個(gè)TableView都能拿來(lái)就直接使用抚垃。

那么這個(gè)解耦的類我們要怎么寫(xiě)呢茉兰?

好的大磺,我們來(lái)新建一個(gè)文件负蠕。


helper類

這個(gè)類只需要一個(gè)屬性坟募,是一個(gè)數(shù)組寒锚。就是你平常寫(xiě)TableView的時(shí)候的數(shù)據(jù)源粹湃。

然后在.m中我們就可以像平常寫(xiě)TableView一樣在這里面寫(xiě)代理了蕴侧。

假裝寫(xiě)了兩個(gè)代理

無(wú)視我的cell和model呵哨,嫌累沒(méi)創(chuàng)建=谤逼。=

最后在VC中把TableView的dataSource設(shè)成Helper就好了。

無(wú)視我這代碼仇穗,我就是給你展現(xiàn)個(gè)邏輯流部,細(xì)寫(xiě)嫌累

重點(diǎn)是別忘了持有helper類。tableView對(duì)dataSource是弱引用纹坐,如果不持有helper就被釋放了枝冀。
就是這么一個(gè)思路。的確該寫(xiě)你都寫(xiě)了,不過(guò)好處就是你以后把helper類拿到另一個(gè)工程還可以直接用果漾。

恩球切,思路就是這么簡(jiǎn)單的一個(gè)思路,不過(guò)你可以把你的helper類寫(xiě)的功能更加豐富一些绒障。比如說(shuō)我的helper類吨凑。老司機(jī)添加了高度緩存、滾動(dòng)優(yōu)化等優(yōu)化功能户辱,并且對(duì)選擇鸵钝、展示動(dòng)畫(huà)、無(wú)數(shù)據(jù)占位圖等常用功能都進(jìn)行了支持庐镐。而且老司機(jī)也在不斷的豐富helper類的功能恩商。

只放一個(gè)版本更新記錄吧,代碼放不下=必逆。=

/**
DWTableViewHelper
TableView工具類
抽出TableView代理怠堪,減小VC壓力,添加常用代理映射

version 1.0.0
添加常用代理映射
添加helper基礎(chǔ)屬性

version 1.0.1
去除注冊(cè)名眉,改為更適用的重用模式

version 1.0.2
添加多分組模式

version 1.0.3
添加選擇模式及相關(guān)api

version 1.0.4
添加helper設(shè)置cell類型及復(fù)用標(biāo)識(shí)

version 1.0.5
將cell的基礎(chǔ)屬性提出協(xié)議粟矿,helper與model同時(shí)遵守協(xié)議

version 1.0.6
修正占位視圖展示時(shí)機(jī),提供兩個(gè)刷新列表擴(kuò)展方法损拢,提供展示嚷炉、隱藏占位圖接口

version 1.0.7
添加選則模式下單選多選控制

version 1.0.8
補(bǔ)充組頭視圖、尾視圖行高代理映射并簡(jiǎn)化代理鏈

version 1.0.9
cell基類添加父類實(shí)現(xiàn)強(qiáng)制調(diào)用宏探橱、斷言中給出未能加載的cell類名

version 1.1.0
改變cell劃線機(jī)制,改為系統(tǒng)分割線绘证,添加分割線歸0方法
添加自動(dòng)行高計(jì)算并緩存
cell添加xib支持
修復(fù)選擇模式選中后關(guān)閉再次開(kāi)啟選擇同一個(gè)無(wú)法選中bug
更換去除選擇背景方式隧膏,解決與選擇模式的沖突
映射所有代理

version 1.1.1
添加自適應(yīng)模式最小行高限制及最大行高設(shè)置
添加數(shù)據(jù)源的容錯(cuò)機(jī)制,但這并不是你故意寫(xiě)錯(cuò)的理由=嚷那。=
添加屏幕判斷胞枕,當(dāng)位置方向時(shí),默認(rèn)返回豎屏
額外補(bǔ)充動(dòng)畫(huà)代理魏宽、支持CAAnimation及DWAnimation

version 1.1.2
展示動(dòng)畫(huà)邏輯修改腐泻,DWAnimation動(dòng)畫(huà)展示方法替換

version 1.1.3
滾動(dòng)優(yōu)化模式添加
高速忽略模式完成
懶加載模式完成
懶加載模式動(dòng)畫(huà)隱藏,更加平滑队询,修復(fù)刷新bug派桩。
有沒(méi)有美工妹子給切幾張占位圖。蚌斩。我做的圖太丑了铆惑。。

*/

是的,所以說(shuō)你玩去那可以寫(xiě)一個(gè)什么都能做的Helper员魏。

正如我最開(kāi)始的效果圖丑蛤。如果你想看看我還對(duì)Helper做了什么你可以去我的倉(cāng)庫(kù)上面看DWTableViewHelper

你想直接用也可以撕阎,你可以去GitHub上面直接托一份受裹,也可以用cocoaPods集成:

      pod 'DWTableViewHelper', '~> 1.1.2'

DWTableViewHelper類當(dāng)前為1.1.2版本,滾動(dòng)優(yōu)化在1.1.3版本pod還沒(méi)有發(fā)虏束,因?yàn)樵跍y(cè)試看有沒(méi)有什么bug棉饶,而且老司機(jī)做的圖有的丑,急需會(huì)美工的妹子幫我切兩張圖魄眉,漢子也行砰盐,愿意幫忙的私信我=。=

如果你想看看老司機(jī)的所有pods項(xiàng)目的話坑律,你也可以打開(kāi)終端岩梳,輸入

pod search wicky
pod search wicky

最后,雙擊666晃择,加波關(guān)注冀值,點(diǎn)波star,老鐵沒(méi)毛补馈列疗!


老鐵沒(méi)毛病
老鐵沒(méi)毛病
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市浪蹂,隨后出現(xiàn)的幾起案子抵栈,更是在濱河造成了極大的恐慌,老刑警劉巖坤次,帶你破解...
    沈念sama閱讀 216,372評(píng)論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件古劲,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡缰猴,警方通過(guò)查閱死者的電腦和手機(jī)产艾,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)滑绒,“玉大人闷堡,你說(shuō)我怎么就攤上這事∫晒剩” “怎么了杠览?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,415評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)纵势。 經(jīng)常有香客問(wèn)我倦零,道長(zhǎng)误续,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,157評(píng)論 1 292
  • 正文 為了忘掉前任扫茅,我火速辦了婚禮蹋嵌,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘葫隙。我一直安慰自己栽烂,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,171評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布恋脚。 她就那樣靜靜地躺著腺办,像睡著了一般。 火紅的嫁衣襯著肌膚如雪糟描。 梳的紋絲不亂的頭發(fā)上怀喉,一...
    開(kāi)封第一講書(shū)人閱讀 51,125評(píng)論 1 297
  • 那天,我揣著相機(jī)與錄音船响,去河邊找鬼躬拢。 笑死,一個(gè)胖子當(dāng)著我的面吹牛见间,可吹牛的內(nèi)容都是我干的聊闯。 我是一名探鬼主播,決...
    沈念sama閱讀 40,028評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼米诉,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼菱蔬!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起史侣,我...
    開(kāi)封第一講書(shū)人閱讀 38,887評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤拴泌,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后惊橱,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體蚪腐,經(jīng)...
    沈念sama閱讀 45,310評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,533評(píng)論 2 332
  • 正文 我和宋清朗相戀三年李皇,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片宙枷。...
    茶點(diǎn)故事閱讀 39,690評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡掉房,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出慰丛,到底是詐尸還是另有隱情卓囚,我是刑警寧澤,帶...
    沈念sama閱讀 35,411評(píng)論 5 343
  • 正文 年R本政府宣布诅病,位于F島的核電站哪亿,受9級(jí)特大地震影響粥烁,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜蝇棉,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,004評(píng)論 3 325
  • 文/蒙蒙 一讨阻、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧篡殷,春花似錦钝吮、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,659評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至劲弦,卻和暖如春耳标,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背邑跪。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,812評(píng)論 1 268
  • 我被黑心中介騙來(lái)泰國(guó)打工次坡, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人呀袱。 一個(gè)月前我還...
    沈念sama閱讀 47,693評(píng)論 2 368
  • 正文 我出身青樓贸毕,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親夜赵。 傳聞我的和親對(duì)象是個(gè)殘疾皇子明棍,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,577評(píng)論 2 353

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