【Koltin Flow(三)】Flow操作符之中間操作符(一)

目錄

【Koltin Flow(一)】五種創(chuàng)建flow的方式
【Koltin Flow(二)】Flow操作符之末端操作符
【Koltin Flow(三)】Flow操作符之中間操作符(一)
【Koltin Flow(三)】Flow操作符之中間操作符(二)
【Koltin Flow(三)】Flow操作符之中間操作符(三)
【Koltin Flow(四)】Flow背壓
【Koltin Flow(五)】SharedFlow及StateFlow

前言

  1. flow的中間操作符比較多,根據(jù)作用大概可以分為幾個類,如變換操作符、過濾操作符等癣疟。
  2. 本篇主要介紹的有變換操作符边器、過濾操作符乔宿、也包含其他的一些操作符裙秋。

變換操作符

1.map牺堰、mapLatest桥狡、mapNotNull搅裙,map實(shí)現(xiàn)直接的變換操作,collect接收到的為變換后的值裹芝,mapLatest則類似于collectLatest變換最新的值部逮,如果來不及變換為上一個則直接取消,變換當(dāng)前最新的值嫂易,mapNotNull則返回變換后不為空的值兄朋。

代碼如下:
          val flow = flow {
                repeat(10){
                    delay(10)
                    emit(it)
                }
            }

            flow.map {
                "map $it"
            }.collect {
                Log.d(TAG.TAG,it)
            }

            flow.mapLatest {
                delay(15)
                "mapLatest $it"
            }.collect {
                Log.d(TAG.TAG,it)
            }

            flow.mapNotNull {
                if (it % 2 == 0){
                    "mapNotNull $it"
                }else{
                    null
                }
            }.collect {
                Log.d(TAG.TAG,it)
            }
日志如下:
2022-07-29 15:37:01.824 10589-10614/edu.test.demo D/Test-TAG: map 0
2022-07-29 15:37:01.836 10589-10614/edu.test.demo D/Test-TAG: map 1
2022-07-29 15:37:01.853 10589-10614/edu.test.demo D/Test-TAG: map 2
2022-07-29 15:37:01.865 10589-10614/edu.test.demo D/Test-TAG: map 3
2022-07-29 15:37:01.880 10589-10614/edu.test.demo D/Test-TAG: map 4
2022-07-29 15:37:01.892 10589-10614/edu.test.demo D/Test-TAG: map 5
2022-07-29 15:37:01.904 10589-10614/edu.test.demo D/Test-TAG: map 6
2022-07-29 15:37:01.915 10589-10614/edu.test.demo D/Test-TAG: map 7
2022-07-29 15:37:01.926 10589-10614/edu.test.demo D/Test-TAG: map 8
2022-07-29 15:37:01.937 10589-10614/edu.test.demo D/Test-TAG: map 9
2022-07-29 15:37:02.108 10589-10617/edu.test.demo D/Test-TAG: mapLatest 9
2022-07-29 15:37:02.128 10589-10615/edu.test.demo D/Test-TAG: mapNotNull 0
2022-07-29 15:37:02.149 10589-10615/edu.test.demo D/Test-TAG: mapNotNull 2
2022-07-29 15:37:02.171 10589-10615/edu.test.demo D/Test-TAG: mapNotNull 4
2022-07-29 15:37:02.196 10589-10615/edu.test.demo D/Test-TAG: mapNotNull 6
2022-07-29 15:37:02.218 10589-10615/edu.test.demo D/Test-TAG: mapNotNull 8
分析:
  • map轉(zhuǎn)換為字符串之后直接全部接收到。
  • mapLatest 因?yàn)檗D(zhuǎn)換的時(shí)候做了延時(shí)怜械,超過了發(fā)送的延時(shí)颅和,所以前面的全部被取消了傅事,只留下了最新的值9。
  • mapNotNull 因?yàn)樵谵D(zhuǎn)換的時(shí)候?qū)⒉荒鼙?整除的數(shù)轉(zhuǎn)換為了null峡扩,所以都沒接收到蹭越,只接收到了偶數(shù)。
  1. transform教届、transformLatest响鹃、transformWhile ,transform直接進(jìn)行轉(zhuǎn)換案训,和map不同的是transform可以控制流速买置,transformLatest則進(jìn)行最新值的轉(zhuǎn)換,類似于mapLatest 强霎,transformWhile則要求閉包返回一個boolean值忿项,為true則繼續(xù)返回,為false則后續(xù)的值全部取消脆栋。
代碼如下:
          val flow = flow {
                repeat(10){
                    delay(10)
                    emit(it)
                }
            }
           flow.transform {
                delay(1000)
                emit(it*10)
            }.collect {
                Log.d(TAG.TAG,"transform is $it")
            }

            flow.transformLatest {
                delay(1000)
                emit("transformLatest $it")
            }.collect {
                Log.d(TAG.TAG,it)
            }

            flow.transformWhile {
                emit("transformWhile $it")
                it!=5
            }.collect {
                Log.d(TAG.TAG,it)
            }

日志如下:
2022-07-29 15:37:03.243 10589-10615/edu.test.demo D/Test-TAG: transform is 0
2022-07-29 15:37:04.255 10589-10615/edu.test.demo D/Test-TAG: transform is 10
2022-07-29 15:37:05.269 10589-10615/edu.test.demo D/Test-TAG: transform is 20
2022-07-29 15:37:06.281 10589-10615/edu.test.demo D/Test-TAG: transform is 30
2022-07-29 15:37:07.294 10589-10615/edu.test.demo D/Test-TAG: transform is 40
2022-07-29 15:37:08.306 10589-10615/edu.test.demo D/Test-TAG: transform is 50
2022-07-29 15:37:09.318 10589-10615/edu.test.demo D/Test-TAG: transform is 60
2022-07-29 15:37:10.330 10589-10615/edu.test.demo D/Test-TAG: transform is 70
2022-07-29 15:37:11.341 10589-10615/edu.test.demo D/Test-TAG: transform is 80
2022-07-29 15:37:12.353 10589-10615/edu.test.demo D/Test-TAG: transform is 90
2022-07-29 15:37:13.470 10589-10617/edu.test.demo D/Test-TAG: transformLatest 9
2022-07-29 15:37:13.483 10589-10617/edu.test.demo D/Test-TAG: transformWhile 0
2022-07-29 15:37:13.495 10589-10617/edu.test.demo D/Test-TAG: transformWhile 1
2022-07-29 15:37:13.509 10589-10617/edu.test.demo D/Test-TAG: transformWhile 2
2022-07-29 15:37:13.521 10589-10617/edu.test.demo D/Test-TAG: transformWhile 3
2022-07-29 15:37:13.532 10589-10617/edu.test.demo D/Test-TAG: transformWhile 4
2022-07-29 15:37:13.544 10589-10617/edu.test.demo D/Test-TAG: transformWhile 5
分析:
  • 可以看出transform轉(zhuǎn)換的時(shí)候控制了流速倦卖,變成了每秒發(fā)送一個值洒擦,接收到的時(shí)候每秒打印出一個值椿争。
  • transformLatest只轉(zhuǎn)換了最新的值9.
  • transformWhile 因?yàn)樵?的時(shí)候返回了false,所以后面的值全部被取消了熟嫩。

過濾操作符

  1. filter秦踪、filterNot、filterIsInstance掸茅、filterNotNull椅邓、fliter閉包返回一個Boolean值,為true則返回昧狮,false則不返回景馁,filterNot剛好相反;filterIsInstance則進(jìn)行類型過濾逗鸣,如過濾出String或者Int等合住,filterNotNull則過濾null值,返回非空值撒璧。
代碼如下:
            val flow = flow {
                repeat(10){
                    delay(10)
                    emit(it)
                }
            }
            flow.filter {
                it % 2 == 0
            }.collect {
                Log.d(TAG.TAG,"filter $it")
            }

            flow.filterNot {
                it % 2 == 0
            }.collect {
                Log.d(TAG.TAG,"filterNot $it")
            }

            flow {
                emit(1)
                emit("123")
            }.filterIsInstance<String>().collect {
                Log.d(TAG.TAG,"filterIsInstance $it")
            }

            flow {
                emit(1)
                emit(null)
                emit(2)
            }.filterNotNull().collect {
                Log.d(TAG.TAG,"filterNotNull $it")
            }

日志如下:
2022-07-29 15:50:45.376 10675-10703/edu.test.demo D/Test-TAG: filter 0
2022-07-29 15:50:45.400 10675-10703/edu.test.demo D/Test-TAG: filter 2
2022-07-29 15:50:45.422 10675-10703/edu.test.demo D/Test-TAG: filter 4
2022-07-29 15:50:45.444 10675-10703/edu.test.demo D/Test-TAG: filter 6
2022-07-29 15:50:45.466 10675-10703/edu.test.demo D/Test-TAG: filter 8
2022-07-29 15:50:45.505 10675-10703/edu.test.demo D/Test-TAG: filterNot 1
2022-07-29 15:50:45.528 10675-10703/edu.test.demo D/Test-TAG: filterNot 3
2022-07-29 15:50:45.550 10675-10703/edu.test.demo D/Test-TAG: filterNot 5
2022-07-29 15:50:45.574 10675-10703/edu.test.demo D/Test-TAG: filterNot 7
2022-07-29 15:50:45.597 10675-10703/edu.test.demo D/Test-TAG: filterNot 9
2022-07-29 15:50:45.598 10675-10703/edu.test.demo D/Test-TAG: filterIsInstance 123
2022-07-29 15:50:45.600 10675-10703/edu.test.demo D/Test-TAG: filterNotNull 1
2022-07-29 15:50:45.600 10675-10703/edu.test.demo D/Test-TAG: filterNotNull 2
分析:
  • 可以看出 filter 滿足條件過濾出了偶數(shù)透葛。
  • filterNot同樣的條件剛好相反,過濾出了奇數(shù)卿樱。
  • filterIsInstance過濾出了字符串僚害。
  • filterNotNull過濾了空值。
  1. take繁调、takeWhile萨蚕、drop靶草、dropWhile,take則是取幾個值返回岳遥,takeWhile按條件取值爱致,如果滿足條件就返回,不滿足則后面全部取消寒随。drop和take相反糠悯,dropWhile和takeWhile相反。
代碼如下:
            val flow = flow {
                repeat(10){
                    delay(10)
                    emit(it)
                }
            }
              flow.take(5).collect {
                Log.d(TAG.TAG,"take $it")
            }

            flow.takeWhile {
                it < 5
            }.collect {
                Log.d(TAG.TAG,"takeWhile $it")
            }

            flow.drop(5).collect {
                Log.d(TAG.TAG,"drop $it")
            }
            flow.dropWhile {
                it < 5
            }.collect {
                Log.d(TAG.TAG,"dropWhile $it")
            }
日志如下:
2022-07-29 16:04:08.109 11070-11096/edu.test.demo D/Test-TAG: take 0
2022-07-29 16:04:08.120 11070-11096/edu.test.demo D/Test-TAG: take 1
2022-07-29 16:04:08.132 11070-11096/edu.test.demo D/Test-TAG: take 2
2022-07-29 16:04:08.144 11070-11096/edu.test.demo D/Test-TAG: take 3
2022-07-29 16:04:08.169 11070-11096/edu.test.demo D/Test-TAG: take 4
2022-07-29 16:04:08.184 11070-11096/edu.test.demo D/Test-TAG: takeWhile 0
2022-07-29 16:04:08.197 11070-11096/edu.test.demo D/Test-TAG: takeWhile 1
2022-07-29 16:04:08.207 11070-11096/edu.test.demo D/Test-TAG: takeWhile 2
2022-07-29 16:04:08.218 11070-11096/edu.test.demo D/Test-TAG: takeWhile 3
2022-07-29 16:04:08.229 11070-11096/edu.test.demo D/Test-TAG: takeWhile 4
2022-07-29 16:04:08.320 11070-11096/edu.test.demo D/Test-TAG: drop 5
2022-07-29 16:04:08.332 11070-11096/edu.test.demo D/Test-TAG: drop 6
2022-07-29 16:04:08.343 11070-11096/edu.test.demo D/Test-TAG: drop 7
2022-07-29 16:04:08.355 11070-11096/edu.test.demo D/Test-TAG: drop 8
2022-07-29 16:04:08.366 11070-11096/edu.test.demo D/Test-TAG: drop 9
2022-07-29 16:04:08.435 11070-11096/edu.test.demo D/Test-TAG: dropWhile 5
2022-07-29 16:04:08.446 11070-11096/edu.test.demo D/Test-TAG: dropWhile 6
2022-07-29 16:04:08.457 11070-11096/edu.test.demo D/Test-TAG: dropWhile 7
2022-07-29 16:04:08.467 11070-11096/edu.test.demo D/Test-TAG: dropWhile 8
2022-07-29 16:04:08.478 11070-11096/edu.test.demo D/Test-TAG: dropWhile 9
分析:
  • 可以看出take5 就取了前面五個進(jìn)行返回妻往,drop剛好相反互艾。
  • takeWhile則返回了滿足條件的前五個,后面的全部取消讯泣,dropWhile剛好相反纫普。
  • 也會有人有疑問,后面的都大于等于5了好渠,所以都取消了昨稼,那后面如果出現(xiàn)個1呢,還會不會返回拳锚,那么再看如下代碼假栓,可以看出,后面即使出現(xiàn)滿足條件的也被全部取消了:
flow{
                emit(1)
                emit(2)
                emit(5)
                emit(1)
                emit(2)
            }.takeWhile {
                it<5
            }.collect {
                Log.d(TAG.TAG,"takeWhile $it")
            }
2022-07-29 16:04:08.087 11070-11096/edu.test.demo D/Test-TAG: takeWhile 1
2022-07-29 16:04:08.087 11070-11096/edu.test.demo D/Test-TAG: takeWhile 2
  • 當(dāng)然這個結(jié)論從源碼也可以看出來霍掺,在注釋的地方直接拋出異常匾荆,后續(xù)不會再執(zhí)行,如下:
// Internal building block for non-tailcalling flow-truncating operators
internal suspend inline fun <T> Flow<T>.collectWhile(crossinline predicate: suspend (value: T) -> Boolean) {
    val collector = object : FlowCollector<T> {
        override suspend fun emit(value: T) {
            // Note: we are checking predicate first, then throw. If the predicate does suspend (calls emit, for example)
            // the the resulting code is never tail-suspending and produces a state-machine
            if (!predicate(value)) {
                //此處predicate如果返回false直接拋出異常
                throw AbortFlowException(this)
            }
        }
    }
    try {
        collect(collector)
    } catch (e: AbortFlowException) {
        e.checkOwnership(collector)
    }
}

  1. debounce杆烁、sample,debounce是超時(shí)取值牙丽,一個值發(fā)送之后,計(jì)時(shí)多少秒再取下一個值兔魂,二sample則屬于周期性取值烤芦,每隔一定的時(shí)間周期取最新的值。
代碼如下:
            flow {
                emit(1)
                delay(10)
                emit(2)
                delay(1000)
                emit(100)
                delay(500)
                emit(200)
            }.debounce(1000).collect {
                Log.d(TAG.TAG,"debounce $it")
            }

            flow {
                emit(1)
                delay(400)
                emit(2)
                delay(400)
                emit(100)
                emit(200)
                delay(200)
            }.sample(500).collect {
                Log.d(TAG.TAG,"sample $it")
            }
日志如下:
2022-08-01 10:10:12.716 3651-3679/edu.test.demo D/Test-TAG: debounce 2
2022-08-01 10:10:13.221 3651-3679/edu.test.demo D/Test-TAG: debounce 200
2022-08-01 10:10:13.724 3651-3679/edu.test.demo D/Test-TAG: sample 2
2022-08-01 10:10:14.226 3651-3679/edu.test.demo D/Test-TAG: sample 200
分析:
  • 我們看出debounce 取值為2,200析校,原因?yàn)榈谝淮伟l(fā)送為1 之后1000ms內(nèi)又發(fā)送了构罗,所以1被覆蓋,2之后1000ms內(nèi)未發(fā)送值勺良,所以2被打印绰播,后面同理,100被200覆蓋尚困,最后打印出了200.
  • sample 取值也為2,200蠢箩,原因?yàn)?00ms,第一個周期內(nèi)(0-500ms),1被2覆蓋谬泌,打印了2滔韵,第二個周期內(nèi)(500-1000ms),100被200覆蓋掌实,打印了2
  1. distinctUntilChanged陪蜻、distinctUntilChanged()、distinctUntilChangedBy贱鼻,用于去除滿足一定條件的值宴卖,如distinctUntilChanged()去重,如果兩個連續(xù)的值一樣邻悬,則跳過當(dāng)前值症昏,繼續(xù)發(fā)送后面的值,屬于distinctUntilChanged的簡化用法父丰,distinctUntilChanged還可以實(shí)現(xiàn)其他的功能肝谭,如只打印比當(dāng)前值大的值,條件返回為boolean蛾扇,為false打印攘烛,為true直接過濾,distinctUntilChangedBy也是去重镀首,但是條件字段可以自定義坟漱,如根據(jù)bean的某一個值去重。
代碼如下:
            flow {
                emit(1)
                emit(2)
                emit(3)
                emit(1)
                emit(1)
                emit(1)
            }.distinctUntilChanged().collect {
                Log.d(TAG.TAG,"distinctUntilChanged  $it")
            }

            flow {
                emit(1)
                emit(2)
                emit(3)
                emit(1)
                emit(1)
                emit(1)
            }.distinctUntilChanged { old, new ->
                old > new
            }.collect {
                Log.d(TAG.TAG,"distinctUntilChanged(old, new)  $it")
            }
            
            flow {
                emit(1)
                emit(2)
                emit(3)
                emit(1)
                emit(1)
                emit(1)
            }.distinctUntilChangedBy {
                it
            }.collect {
                Log.d(TAG.TAG,"distinctUntilChangedBy  $it")
            }
日志如下:
2022-08-01 10:33:56.073 4332-4359/edu.test.demo D/Test-TAG: distinctUntilChanged  1
2022-08-01 10:33:56.073 4332-4359/edu.test.demo D/Test-TAG: distinctUntilChanged  2
2022-08-01 10:33:56.074 4332-4359/edu.test.demo D/Test-TAG: distinctUntilChanged  3
2022-08-01 10:33:56.074 4332-4359/edu.test.demo D/Test-TAG: distinctUntilChanged  1
2022-08-01 10:33:56.074 4332-4359/edu.test.demo D/Test-TAG: distinctUntilChanged(old, new)  1
2022-08-01 10:33:56.075 4332-4359/edu.test.demo D/Test-TAG: distinctUntilChanged(old, new)  2
2022-08-01 10:33:56.075 4332-4359/edu.test.demo D/Test-TAG: distinctUntilChanged(old, new)  3
2022-08-01 10:33:56.075 4332-4359/edu.test.demo D/Test-TAG: distinctUntilChangedBy  1
2022-08-01 10:33:56.076 4332-4359/edu.test.demo D/Test-TAG: distinctUntilChangedBy  2
2022-08-01 10:33:56.076 4332-4359/edu.test.demo D/Test-TAG: distinctUntilChangedBy  3
2022-08-01 10:33:56.076 4332-4359/edu.test.demo D/Test-TAG: distinctUntilChangedBy  1
分析:
  • 可以看出distinctUntilChanged()直接去除了后面兩個重復(fù)的1蘑斧, distinctUntilChanged則值打印出來了后面比前面大的值靖秩,后面3個1沒打印须眷,如果要實(shí)現(xiàn)去重竖瘾,只需要將old>new改成old==new。distinctUntilChangedBy也實(shí)現(xiàn)了去重的效果花颗。

總結(jié)

  • 本篇主要介紹了中間操作符的一部分捕传,其他的在下一篇繼續(xù)介紹。
  • 本篇設(shè)計(jì)到中間操作符的兩類操作符扩劝,分別為變換操作符庸论、過濾操作符。
  • 操作符本身的理解并不難棒呛,只要總結(jié)起來結(jié)合具體的代碼去理解就會比較容易聂示。
  • 本篇為自己學(xué)習(xí)及使用過程中的總結(jié),難免存在錯誤或思維局限簇秒,歡迎大家討論指正鱼喉。
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子扛禽,更是在濱河造成了極大的恐慌锋边,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,277評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件编曼,死亡現(xiàn)場離奇詭異豆巨,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)掐场,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評論 3 393
  • 文/潘曉璐 我一進(jìn)店門往扔,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人熊户,你說我怎么就攤上這事瓤球。” “怎么了敏弃?”我有些...
    開封第一講書人閱讀 163,624評論 0 353
  • 文/不壞的土叔 我叫張陵卦羡,是天一觀的道長。 經(jīng)常有香客問我麦到,道長绿饵,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,356評論 1 293
  • 正文 為了忘掉前任瓶颠,我火速辦了婚禮拟赊,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘粹淋。我一直安慰自己吸祟,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,402評論 6 392
  • 文/花漫 我一把揭開白布桃移。 她就那樣靜靜地躺著屋匕,像睡著了一般。 火紅的嫁衣襯著肌膚如雪借杰。 梳的紋絲不亂的頭發(fā)上过吻,一...
    開封第一講書人閱讀 51,292評論 1 301
  • 那天,我揣著相機(jī)與錄音蔗衡,去河邊找鬼纤虽。 笑死,一個胖子當(dāng)著我的面吹牛绞惦,可吹牛的內(nèi)容都是我干的逼纸。 我是一名探鬼主播,決...
    沈念sama閱讀 40,135評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼济蝉,長吁一口氣:“原來是場噩夢啊……” “哼杰刽!你這毒婦竟也來了呻纹?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,992評論 0 275
  • 序言:老撾萬榮一對情侶失蹤专缠,失蹤者是張志新(化名)和其女友劉穎雷酪,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體涝婉,經(jīng)...
    沈念sama閱讀 45,429評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡哥力,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,636評論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了墩弯。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片吩跋。...
    茶點(diǎn)故事閱讀 39,785評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖渔工,靈堂內(nèi)的尸體忽然破棺而出锌钮,到底是詐尸還是另有隱情,我是刑警寧澤引矩,帶...
    沈念sama閱讀 35,492評論 5 345
  • 正文 年R本政府宣布梁丘,位于F島的核電站,受9級特大地震影響旺韭,放射性物質(zhì)發(fā)生泄漏氛谜。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,092評論 3 328
  • 文/蒙蒙 一区端、第九天 我趴在偏房一處隱蔽的房頂上張望值漫。 院中可真熱鬧,春花似錦织盼、人聲如沸杨何。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽危虱。三九已至,卻和暖如春谋国,著一層夾襖步出監(jiān)牢的瞬間槽地,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評論 1 269
  • 我被黑心中介騙來泰國打工芦瘾, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人集畅。 一個月前我還...
    沈念sama閱讀 47,891評論 2 370
  • 正文 我出身青樓近弟,卻偏偏與公主長得像,于是被迫代替她去往敵國和親挺智。 傳聞我的和親對象是個殘疾皇子祷愉,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,713評論 2 354

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