Dart API 學(xué)習(xí)記錄(二)

Dart API 學(xué)習(xí)記錄(一) http://www.reibang.com/p/388d986c0f48

Dart API 學(xué)習(xí)記錄(二)

dart:async庫(kù)

dart:async庫(kù)是Dart 語(yǔ)言支持異步編程的基礎(chǔ)友浸。
庫(kù)中提供了Future 類(lèi)和Stream 類(lèi)灭抑。這兩個(gè)類(lèi)是理解Dart 語(yǔ)言異步機(jī)制的基礎(chǔ)镐躲。

在使用前async 庫(kù)的功能前需要在代碼中添加如下語(yǔ)句:

import 'dart:async'

Future 類(lèi)

Future 對(duì)象返回值表明當(dāng)前時(shí)刻的計(jì)算結(jié)果可能還不可用十拣。
Future 實(shí)例會(huì)在計(jì)算結(jié)束后再返回結(jié)果橙依,而不是現(xiàn)在立即返回眨八。

Future 通常用來(lái)操作冗長(zhǎng)的計(jì)算钞它,比如大規(guī)模的I/O 操作或與用戶進(jìn)行交互坡垫。

下面的例子將返回一個(gè)Future:

import 'dart:io';

void bindServer(){
  HttpServer.bind('127.0.0.1', 4444)
      .then((server) => print('${server.isBroadcast}'))
      .catchError(print);
}
void main(){
  bindServer();
}

在例子中Future.then注冊(cè)了一個(gè)回調(diào)函數(shù)彭沼,當(dāng)bind() 方法執(zhí)行完成后開(kāi)始運(yùn)行缔逛。回調(diào)函數(shù)的功能是: 當(dāng)bind()執(zhí)行成功后會(huì)返回一個(gè)HttpServer 的對(duì)象,在回調(diào)函數(shù)中會(huì)返回該HttpServer的一個(gè)熟悉值褐奴。

Stream 類(lèi)

一個(gè)Stream 對(duì)象提供了一個(gè)異步數(shù)據(jù)的隊(duì)列按脚。在這個(gè)隊(duì)列中可能包含事件(鼠標(biāo)點(diǎn)擊),大數(shù)據(jù)塊.

利用Stream 方法來(lái)讀取文件的例子:

import 'dart:async';
import 'dart:io';
import 'dart:convert';

void readFile(f){
  Stream<List<int>> stream = new File(f).openRead();
  stream.transform(UTF8.decoder).listen(print);
}
void main(){
  String filename = "/opt/program/Dart/dart-code/test_data/temp.py";
  readFile(filename);

Asynchronous Programming: Futures

以下的內(nèi)容來(lái)源于下列地址:
https://www.dartlang.org/tutorials/language/futures

要點(diǎn)總結(jié)

  • Dart 語(yǔ)言是單線程的敦冬。
  • 同步的代碼可能導(dǎo)致代碼阻塞辅搬。
  • 可以使用Future 方法來(lái)執(zhí)行異步操作。
  • 在異步方法里使用await()來(lái)暫停代碼執(zhí)行脖旱,直到Future 執(zhí)行完成堪遂。
  • 也可使用Future 的then()方法來(lái)實(shí)現(xiàn)上面的目的。
  • 在異步方法里使用try...catch...來(lái)獲取異常萌庆。
  • 也可是使用Future 的catchError()方法來(lái)實(shí)現(xiàn)上面的目的溶褪。
  • 可以就多個(gè)異步的方法鏈接起來(lái)順序執(zhí)行。

簡(jiǎn)介

可能導(dǎo)致代碼阻塞的例子:

void printDailyNewsDigest(){
// Synchronous code
    String news = gatherNewsReports(); // Can take a while.
    print(news);

}
String gatherNewsReports(){
  return "<gathered news goes here>";
}
String printWinningLotteryNumbers(){
  return "Winning lotto numbers: [23, 63, 87, 26, 2]";
}
String printWeatherForecast(){
  return "Tomorrow's forecast: 70F, sunny";
}
String printBaseballScore(){
  return "Baseball score: Red Sox 10, Yankees 0";
}


void main(){
  printDailyNewsDigest();
  printWinningLotteryNumbers();
  printWeatherForecast();
  printBaseballScore();
}

對(duì)應(yīng)輸出為:

<gathered news goes here>
Winning lotto numbers: [23, 63, 87, 26, 2]
Tomorrow's forecast: 70F, sunny
Baseball score: Red Sox 10, Yankees 0

使用說(shuō)明

Future 代表著在將來(lái)會(huì)獲取到一個(gè)值踊兜。
當(dāng)Future 被調(diào)用時(shí)竿滨,會(huì)發(fā)生:

  1. 將需要完成的工作進(jìn)行隊(duì)列化并返回一個(gè)Future 的對(duì)象。
  2. 當(dāng)待執(zhí)行的工作完成并獲取到最后的值后捏境,F(xiàn)uture 對(duì)象以這個(gè)值結(jié)束于游。

可以通過(guò)下面的方式獲取Future 的返回值。

  1. 使用async 和 await
  2. 使用Future 提供的API

使用async 和 await實(shí)現(xiàn)異步通信

async 和 await 是Dart 語(yǔ)言中異步編程支持的關(guān)鍵字垫言。使用這兩個(gè)關(guān)鍵字可以在不使用Future API 的情況下實(shí)現(xiàn)異步編程贰剥。

使用async 和 await實(shí)現(xiàn)異步通信的例子:

import 'dart:html';
import 'dart:async';

printWinningLotteryNumbers() {
  print('Winning lotto numbers: [23, 63, 87, 26, 2]');
}

printWeatherForecast() {
  print('Tomorrow\'s forecast: 70F, sunny.');
}

printBaseballScore() {
  print('Baseball score: Red Sox 10, Yankees 0');
}

// Imagine that this function is more complex and slow. :)
Future gatherNewsReports_async() async {
  String path =     'https://www.dartlang.org/f/dailyNewsDigest.txt';
  return (await HttpRequest.getString(path));
}

Future printDailyNewsDigest_async() async {
  String news = await gatherNewsReports_async();
  print(news);
}

void asynchronousCode(){
  printDailyNewsDigest_async();
  printWinningLotteryNumbers();
  printWeatherForecast();
  printBaseballScore();
}

main() {
  asynchronousCode();
}

上面的例子對(duì)應(yīng)的輸出結(jié)果:

Winning lotto numbers: [23, 63, 87, 26, 2]
Tomorrow's forecast: 70F, sunny.
Baseball score: Red Sox 10, Yankees 0
<gathered news goes here>

上面代碼的執(zhí)行流程圖:


async-await
  1. 程序開(kāi)始執(zhí)行。
  2. 主函數(shù)調(diào)用asynchronousCode()函數(shù)筷频。
  3. asynchronousCode()函數(shù)調(diào)用printDailyNewsDigest_async()函數(shù)蚌成,然后函數(shù)立即返回一個(gè)Future 對(duì)象。
  4. asynchronousCode()函數(shù)其它中接下來(lái)的代碼依次開(kāi)始執(zhí)行凛捏。以此執(zhí)行printWinningLotteryNumbers()担忧,printWeatherForecast()printBaseballScore()函數(shù)坯癣,并返回對(duì)應(yīng)的結(jié)果瓶盛。
  5. printDailyNewsDigest_async()函數(shù)體開(kāi)始執(zhí)行。
  6. 當(dāng)執(zhí)行到await 語(yǔ)句時(shí):程序暫停示罗,等待gatherNewsReports_async()函數(shù)執(zhí)行結(jié)果惩猫。
  7. 一旦gatherNewsReports_async()函數(shù)的Future 執(zhí)行完成,printDailyNewsDigest_async()函數(shù)將繼續(xù)執(zhí)行蚜点。
  8. 當(dāng)printDailyNewsDigest_async()函數(shù)執(zhí)行完成后轧房,程序結(jié)束。

處理error

如果Future 的函數(shù)執(zhí)行中發(fā)生了error绍绘,怎Future 的返回值中就會(huì)包含error 信息奶镶。
可以通過(guò)try-catch 語(yǔ)句來(lái)處理這些異常迟赃。

處理異常的例子:

import 'dart:html';
import 'dart:async';

Future printDailyNewsDigest() async {
  try {
    String news = await gatherNewsReports();
    print(news);
  } catch (e) {
    // ... handle error ...
  }
}

main() {
  printDailyNewsDigest();
  printWinningLotteryNumbers();
  printWeatherForecast();
  printBaseballScore();
}

printWinningLotteryNumbers() {
  print('Winning lotto numbers: [23, 63, 87, 26, 2]');
}

printWeatherForecast() {
  print('Tomorrow\'s forecast: 70F, sunny.');
}

printBaseballScore() {
  print('Baseball score: Red Sox 10, Yankees 0');
}

// Imagine that this function is more complex and slow. :)
Future gatherNewsReports() async {
  String path =
      'https://www.dartlang.org/f/dailyNewsDigest.txt';
    String content = await HttpRequest.getString(path);
    return content;
}

順序執(zhí)行

可以使用多個(gè)await 語(yǔ)句來(lái)確認(rèn)上一條一句結(jié)束了才執(zhí)行下面的語(yǔ)句。

例子如下:

// Sequential processing using async and await.
main() async {
  await expensiveA();
  await expensiveB();
  doSomethingWith(await expensiveC());
}

Future API 實(shí)現(xiàn)異步通信

await / async 在Dart 1.9版本里面才添加進(jìn)來(lái)厂镇。

可以通過(guò)`then() 方法來(lái)注冊(cè)一個(gè)回調(diào)函數(shù)捺氢。這個(gè)回調(diào)函數(shù)將在Future 完成后開(kāi)始執(zhí)行。

處理error

在Future API 中提供了catchError()方法來(lái)處理Future 執(zhí)行中的異常剪撬。

調(diào)用多個(gè)Future 類(lèi)型的返回值

使用多個(gè)then() 方法來(lái)鏈接多個(gè)函數(shù)。
expensiveA().then((aValue) => expensiveB())
            .then((bValue) => expensiveC())
            .then((cValue) => doSomethingWith(cValue));

上面的代碼等待expensiveA 執(zhí)行完成后開(kāi)始執(zhí)行expensiveB, 在expensiveB doSomethingWith悠反。

調(diào)用Future.wait() 方法來(lái)鏈接多個(gè)函數(shù)残黑。
// Parallel processing using the Future API
Future.wait([expensiveA(), expensiveB(), expensiveC()])
      .then((List responses) => chooseBestResponse(responses))
      .catchError((e) => handleError(e));

上面的代碼等待expensiveA(), expensiveB(), expensiveC() 都執(zhí)行完成后才開(kāi)始執(zhí)行then() 中的例子。

Asynchronous Programming: Streams

以下的內(nèi)容來(lái)源于下列地址:
https://www.dartlang.org/tutorials/language/streams

要點(diǎn)

  1. Stream 提供數(shù)據(jù)的異步隊(duì)列
  2. 數(shù)據(jù)隊(duì)列里面包含用戶交互數(shù)據(jù)斋否,或從文件中讀取的數(shù)據(jù)梨水。
  3. 可以使用await forlisten()來(lái)處理stream 對(duì)象的數(shù)據(jù)。
  4. Stream API 提供錯(cuò)誤處理茵臭。
  5. 包含兩種類(lèi)型的Stream:?jiǎn)蝹€(gè)訂閱疫诽,廣播Stream

接受Stream 事件

雖然Stream 對(duì)象的創(chuàng)建有很多種方法,但是使用方法卻是相同的旦委。使用方法: 使用 await for語(yǔ)句去操作一個(gè)Stream 對(duì)象的事件的迭代對(duì)象奇徒,就像for 循環(huán)操作迭代對(duì)象一樣。

await for語(yǔ)句只能操作使用async關(guān)鍵字標(biāo)記的函數(shù)缨硝。
例子如下:

import 'dart:async';

Future<int> sumStream(Stream<int> stream) async {
  var sum = 0;
  await for (var value in stream) {
    sum += value;
  }
  return sum;
}

Stream<int> countStream(int to) async* {
  for (int i = 1; i <= to; i++) {
    yield i;
  }
}

main() async {
  var stream = countStream(10);
  var sum = await sumStream(stream);
  print(sum); // 55
}

錯(cuò)誤事件

當(dāng)沒(méi)有收到新的事件時(shí)摩钙,Stream 對(duì)象會(huì)結(jié)束運(yùn)行。
當(dāng)接受到新事件的時(shí)候查辩,系統(tǒng)胡通知Stream 收到了新的事件胖笛。
當(dāng)讀取到的Stream 事件在await for 循環(huán)執(zhí)行時(shí),當(dāng)Stream 結(jié)束后宜岛,await for 循環(huán)也就結(jié)束了长踊。

當(dāng)Stream 對(duì)象運(yùn)行過(guò)程中有錯(cuò)誤發(fā)生,大部分的Stream 將停止萍倡。同時(shí)Stream 對(duì)象將至少發(fā)送一條錯(cuò)誤信息身弊。
可以使用try-catch 語(yǔ)句間await for 語(yǔ)句包括起來(lái),用這種方法來(lái)處理error 信息遣铝。

處理Stream 錯(cuò)誤的例子:

import 'dart:async';

Future<int> sumStream(Stream<int> stream) async {
  var sum = 0;
  try {
    await for (var value in stream) {
      sum += value;
    }
  } catch (error) {
    return -1;
  }
  return sum;
}

Stream<int> countStream(int to) async* {
  for (int i = 1; i <= to; i++) {
    if (i == 4) {
      throw "Whoops!";  // Intentional error
    } else {
      yield i;
    }
  }
}

main() async {
  var stream = countStream(10);
  var sum = await sumStream(stream);
  print(sum); // -1
}

Stream 對(duì)象處理

可以很方便的通過(guò)Stream 的await for 循環(huán)來(lái)依次處理相應(yīng)的事件佑刷。

下面的例子,可以方便找到 數(shù)值 > 0的數(shù)值的下標(biāo)位置酿炸。

import 'dart:async';

Future<int> lastPositive(Stream<int> stream) async {
  var lastValue = null;
  await for (var value in stream) {
    if (value < 0) continue;
    lastValue = value;
  }
  return lastValue;
}

main() async {
  var data = [1, -2, 3, -4, 5, -6, 7, -8, 9, -10];
  var stream = new Stream.fromIterable(data);
  var lastPos = await lastPositive(stream);
  print(lastPos); // 9
}

Stream 兩種類(lèi)型

單個(gè)訂閱類(lèi)型 (Single subscription streams)

大部分的Stream 實(shí)例會(huì)包含整個(gè)事件隊(duì)列的一部分瘫絮。每一個(gè)事件必須在正確的位置,并且不允許有任何數(shù)據(jù)遺失填硕。這種類(lèi)型類(lèi)似于閱讀文件或接受網(wǎng)頁(yè)服務(wù)麦萤。
這是類(lèi)似于TCP socket鹿鳖,不允許有數(shù)據(jù)遺失。

這種類(lèi)型的Stream壮莹,只能被監(jiān)聽(tīng)一次翅帜。
假如再次監(jiān)聽(tīng),將會(huì)導(dǎo)致之前的事件隊(duì)列丟失命满,并導(dǎo)致Stream 不再接受數(shù)據(jù)涝滴。

廣播類(lèi)型(Broadcast streams)

這種類(lèi)型的Stream 可以只一次處理一個(gè)事件。
可以對(duì)這種類(lèi)型實(shí)施多次監(jiān)聽(tīng)胶台。

Stream 的處理方法

完整方法列表:

返回值 函數(shù)
Future<T\> get first
Future<T> get last
Future<T> get single
Future<int> get length
Future<bool> get isEmpty
Future<T> firstWhere(bool test(T event), {T orElse()})
Future<T> lastWhere(bool test(T event), {T orElse()})
Future<T> singleWhere(bool test(T event), {T orElse()})
Future<T> reduce(T combine(T previous, T element))
Future fold(initialValue, combine(previous, T element))
Future<String> join([String separator = ""])
Future<bool> contains(Object needle)
Future forEach(void action(T element))
Future<bool> every(bool test(T element))
Future<bool> any(bool test(T element))
Future<List<T>> toList()
Future<Set<T>> toSet()
Future<T> elementAt(int index)
Future pipe(StreamConsumer<T> consumer)
Future drain([var futureValue])

簡(jiǎn)單的實(shí)例:

Future<bool> contains(Object element) async {
  await for (var event in this) {
    if (event == element) return true;
  }
  return false;
}

Future forEach(void action(T element)) async {
  await for (var event in this) {
    action(event);
  }
}

Future<List<T>> toList() async {
  var result = <T>[];
  await this.forEach(result.add);
  return result;
}

Future<String> join([String separator = ""]) async {
  return (await this.toList()).join(separator);
}

Stream 對(duì)象的修改方法

方法列表:

返回值 函數(shù)
Stream<T> where(bool test(T event))
Stream map(convert(T event))
Stream expand(Iterable expand(T element);
Stream<T> take(int count)
Stream<T> skip(int count)
Stream<T> takeWhile(bool test(T element))
Stream<T> skipWhile(bool test(T element))
Stream<T> distinct([bool equals(T previous, T next)])
Stream asyncExpand(Stream expand(T element))
Stream asyncMap(Future convert(T event))
Stream timeout(Duration timeLimit, {void onTimeout(EventSink sink)})
Stream<T> handleError(Function onError, {bool test(error)})
Stream transform(StreamTransformer<T, dynamic> streamTransformer)

使用這些函數(shù)歼疮,閱讀文件的例子:

import 'dart:io';
import 'dart:async';
import 'dart:convert';

main(args) async {
  var file = new File(args[0]);
  var lines = file
      .openRead()
      .transform(UTF8.decoder)
      .transform(const LineSplitter());
  await for (var line in lines) {
    if (!line.startsWith('#')) {
      print(line);
    }
  }
}

The listen() method

Stream 的listen() 方法是更底層的方法,其它的Stream的方法都是在listen 之上定義的诈唬。

創(chuàng)建一個(gè)Stream 類(lèi)型時(shí)韩脏,可以只繼承Stream 類(lèi),并實(shí)現(xiàn)listen 方法铸磅。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末赡矢,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子阅仔,更是在濱河造成了極大的恐慌吹散,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,185評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件霎槐,死亡現(xiàn)場(chǎng)離奇詭異送浊,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)丘跌,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,652評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門(mén)袭景,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人闭树,你說(shuō)我怎么就攤上這事耸棒。” “怎么了报辱?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,524評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵与殃,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我碍现,道長(zhǎng)幅疼,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,339評(píng)論 1 293
  • 正文 為了忘掉前任昼接,我火速辦了婚禮爽篷,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘慢睡。我一直安慰自己逐工,他們只是感情好铡溪,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,387評(píng)論 6 391
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著泪喊,像睡著了一般棕硫。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上袒啼,一...
    開(kāi)封第一講書(shū)人閱讀 51,287評(píng)論 1 301
  • 那天哈扮,我揣著相機(jī)與錄音,去河邊找鬼蚓再。 笑死灶泵,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的对途。 我是一名探鬼主播,決...
    沈念sama閱讀 40,130評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼髓棋,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼实檀!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起按声,我...
    開(kāi)封第一講書(shū)人閱讀 38,985評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤膳犹,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后签则,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體须床,經(jīng)...
    沈念sama閱讀 45,420評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,617評(píng)論 3 334
  • 正文 我和宋清朗相戀三年渐裂,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了豺旬。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,779評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡柒凉,死狀恐怖族阅,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情膝捞,我是刑警寧澤坦刀,帶...
    沈念sama閱讀 35,477評(píng)論 5 345
  • 正文 年R本政府宣布,位于F島的核電站蔬咬,受9級(jí)特大地震影響鲤遥,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜林艘,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,088評(píng)論 3 328
  • 文/蒙蒙 一盖奈、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧北启,春花似錦卜朗、人聲如沸拔第。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,716評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)蚊俺。三九已至,卻和暖如春逛万,著一層夾襖步出監(jiān)牢的瞬間泳猬,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,857評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工宇植, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留得封,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,876評(píng)論 2 370
  • 正文 我出身青樓指郁,卻偏偏與公主長(zhǎng)得像忙上,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子闲坎,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,700評(píng)論 2 354

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

  • Spring Cloud為開(kāi)發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見(jiàn)模式的工具(例如配置管理疫粥,服務(wù)發(fā)現(xiàn),斷路器腰懂,智...
    卡卡羅2017閱讀 134,654評(píng)論 18 139
  • 異步編程對(duì)JavaScript語(yǔ)言太重要梗逮。Javascript語(yǔ)言的執(zhí)行環(huán)境是“單線程”的,如果沒(méi)有異步編程绣溜,根本...
    呼呼哥閱讀 7,311評(píng)論 5 22
  • 本文是對(duì) Dart 語(yǔ)言的官方文檔做了簡(jiǎn)單的翻譯和總結(jié)慷彤,有不當(dāng)之處敬請(qǐng)指正。如果有時(shí)間和精力建議通讀官方文檔 he...
    小小小超子閱讀 10,518評(píng)論 8 22
  • 此文章是v1.0+時(shí)編寫(xiě)怖喻,年代久遠(yuǎn)底哗,小心有毒,謹(jǐn)慎食用C小K一ⅰ! 一些重要概念 所有的東西都是對(duì)象咒吐,所有的對(duì)象都是類(lèi)的...
    soojade閱讀 10,051評(píng)論 2 27
  • 和Lydia去看了期待已久的烏托邦
    我說(shuō)你瞅啥呀閱讀 111評(píng)論 0 0