Flutter - Stream基礎知識 [復制鏈接]

2019-11-11 10:17
科技在發展 閱讀:245 評論:0 贊:0
Tag:  Flutter Stream

在本指南中,我們將介紹Dart中Steam的基礎知識,如何使用,管理和創建Steam。

什么是Stream

關于如何可視化Stream有很多比較,因此我將使用一個常見的比較。Stream就像管道,您將一個值放在一端,如果另一端有一個偵聽器,則該偵聽器將接收該值。一個Stream可以有多個偵聽器,并且將所有這些偵聽器放入管道后將收到相同的值。將值放在流上的方式是使用StreamController。

如何創建流

如果要創建一個Stream,可以在其中添加值,請從StreamController開始。

StreamController controller = StreamController();

這將構造一個控制器,您可以使用該控制器來操縱該控制器管理的流。可以通過stream屬性訪問控制器流

Stream stream = controller.stream;

如何使用Steam

接下來要做的是能夠從Steam中獲取值。這通常稱為訂閱或收聽Steam。訂閱流時,將僅獲得訂閱后發出的值(放入Steam中)。您可以通過調用該listen函數并為它提供一個Function來訂閱流,以在有新值可用時回調該值,通常將其稱為回調函數,或僅稱為回調。

stream.listen((value) {
print('Value from controller: $value');
});

發射/向Steam添加值

當您訂閱了Steam時,這意味著某個函數正在某處等待執行。通過流發出值的方式是通過調用addstreams控制器。

controller.add(12);

調用該函數時,將執行上一節中提供的回調。

Value from controller: 12

這就是Stream的所有基礎知識。現在讓我們繼續管理Stream。

管理Stream

監聽調用返回StreamSubscriptionStream類型 。這可以用來管理Stream的訂閱。訂閱的最常見用法是在不再需要接收數據時取消監聽。對Stream的訂閱將一直處于活動狀態,直到整個內存(通常是應用程序的整個生命周期)被破壞為止。在某些情況下這是完全可以的,而在其他情況下則不是。

訂閱Stream后,您必須將其取消后,可以將其存儲在 SteamSubscription

StreamSubscription streamSubscription = stream.listen((value) {
print('Value from controller: $value');
});

這將為您提供注冊回調的訂閱對象。

取消stream

當您要執行此操作時,讓我們過去。在flutter中,流通常與一起使用,StreamBuilder一旦窗口小部件銷毀,該流就會在內部為您管理和取消訂閱Stream。要遵循的一個好規則是,當您訂閱Stream時,保留訂閱并在dispose方法中編寫代碼以調用cancel。如果您的流在應用程序的整個過程中都需要保持活動狀態,則無需在處置時或不需要時取消該Stream。

streamSubscription.cancel();

常見Stream錯誤

當開發人員在dart中使用Streams時,很常見的一件事是“Stream已訂閱”消息。很多人認為這是因為存在有效的訂閱和取消操作,可以消除該錯誤,但這不是事實。讓我們看看如何自己創建此異常,然后我們將找出解決方法。

stream.listen((value) {
print('1st Sub: $value');
});
stream.listen((value) {
print('2nd Sub: $value');
});

這將引發錯誤“錯誤狀態:流已被收聽”。現在,即使您取消第一個訂閱并再次訂閱,您仍然會收到此錯誤,這是設計使然。

streamSubscription = stream.listen((value) {
print('1st Sub: $value');
});
await streamSubscription.cancel();
stream.listen((value) {
print('2nd Sub: $value');
});

上面的代碼仍將引發“錯誤狀態”stream錯誤。這樣做的原因是因為stream有兩種類型:

單一訂閱流:與一系列事件結合使用,這些事件是一個較大的整體的一部分。諸如讀取文件或Web請求之類的事情。為了確保首先訂閱的訂閱者以正確的順序獲取所有正確的信息,存在一個限制,即您只能在流存在的生命周期中訂閱一次。

廣播stream:這種流用于單獨的發射,可以一次處理一次,而無需上下文或先前事件的知識。

您可以像我一樣將兩個都用于單個事件,但只是對第一個訂閱策略感到厭倦。當使用StreamBuilderin Flutter時,您很可能總是會遇到異常,因為在構建函數調用期間,Stream將被多次訂閱(這經常發生)。

修復錯誤狀態stream錯誤

要解決此問題,您必須專門創建一個廣播StreamController,以便將基礎流構建和管理為允許多個預訂的廣播stream。

StreamController controller = StreamController.broadcast();

重要說明—使用這些Stream類型中的任何一種并不意味著您不必管理訂閱。如果您手動訂閱了一個Stream,則如果有更改可能需要再次訂閱它,則必須對其進行清理(取消)。多個訂閱會導致內存泄漏,請確保您的代碼何時超出范圍或超出所處置的范圍,然后根據需要重新訂閱。

Manual Streams

創建 Stream的另一種方法也是一種常見方法是通過async *函數。這是一個函數,它將異步運行并在有新值時返回(產生)一個值,但不會停止該函數的執行。為了更有意義,讓我們這樣看。下面是一個Future,它將在等待1秒后返回一個隨機值。

Future getRandomValue() async {
var random = Random(2);
await Future.delayed(Duration(seconds: 1));
return random.nextDouble();
}

可以使用此代碼,一旦關閉,您將獲得一個隨機值,該函數將完成執行。這意味著如果您想要另一個隨機值,則必須調用并再次等待該函數。像下面。

var value1 = await getRandomValue();
var value2 = await getRandomValue();

如果您想一次調用該函數并連續從該函數獲取隨機值而不停止執行該怎么辦?那就是async*產生收益的地方。讓我們創建一個返回Stream的函數,每一秒鐘將發出一個新的隨機值。\

Stream getRandomValues() async* {
var random = Random(2);
while (true) {
await Future.delayed(Duration(seconds: 1));
yield random.nextDouble();
}
}

這稱為生成器功能。它看起來與上一個相似,但是讓我們看一下它們之間的區別。

  • 首先要注意的是,我們現在返回一個Stream而不是一個Future。這意味著我們不必等待值,而必須訂閱Stream。
  • 第二個區別是async*而不是async。這告訴運行時該代碼應異步運行,但是即使“返回”值后執行仍將繼續。
  • 上次不同的是更換return用yield。這基本上是一個返回函數,但不會退出該函數。相反,它在yield之后繼續執行其余代碼。

那么如何使用此Stream(生成器功能)?與上述相同。

getRandomValues().listen((value) {
print('1st: $value');
});

這將打印出類似以下內容的內容,其中每秒鐘延遲后將打印一行。

1st: 0.000783592309359204
1st: 0.232325923093592045
1st: 0.456078359230935920
1st: 0.565783592309359204

默認情況下會廣播以這種方式創建的Stream,并允許多個訂閱。就所有的使用基礎而言,您必須了解Stream。在基礎方面,這是您僅需了解Stream,如何使用它們以及如何有效地管理它們而又不會引起代碼錯誤的全部知識。了解Streams以及它們如何工作并需要更多功能后,您可以查看RxDart。


我來說兩句
您需要登錄后才可以評論 登錄 | 立即注冊
facelist
所有評論(0)
領先的中文移動開發者社區
18620764416
7*24全天服務
意見反饋:[email protected]

掃一掃關注我們

Powered by Discuz! X3.2© 2001-2019 Comsenz Inc.( 粵ICP備15117877號 )

重庆时时彩开奖模拟器 炸金花控牌慢手法视频 第二位杀号 单机捕鱼机 广东十一选五开奖结果 二期时时计划稳定版计划软件 幸运28挂机稳赚方法 股票分析软件排行榜 股票分析软件哪个好 北京pk官方开奖结果 000030股票行情 牛牛手游平台官网app 安徽11选5走势图分布图 聚财网真的能赚钱吗