原文
正文
非同步互動可能需要一個理想的機會來進行總結。偶爾,在週期結束之前可能會發出一些值。在 Dart 中,您可以建立一個返回 Stream 的容量,該容量可以在非同步程式處於活動狀態時發射一些值。假設您需要根據一個 Stream 的快照在 Flutter 中構造一個小部件,那麼有一個名為 StreamBuilder 的小部件。
在這個部落格中,我們將探索 Flutter 中的 StreamBuilder。我們還將實現一個演示程式,並向您展示如何在您的 Flutter 應用程式中使用 StreamBuilder。
介紹:
StreamBuilder 可以監聽公開的流,並返回小部件和捕獲獲得的流資訊的快照。造溪者提出了兩個論點。
A stream
構建器,它可以將流中的多個元件更改為小部件
Stream 像一條線。當您從一端輸入值而從另一端輸入偵聽器時,偵聽器將獲得該值。一個流可以有多個偵聽器,這些偵聽器的負載可以獲得流水線,流水線將獲得等價值。如何在流上放置值是通過使用流控制器實現的。流構建器是一個小部件,它可以將使用者定義的物件更改為流。
建造者:
要使用 StreamBuilder,需要呼叫下面的建構函式:
const StreamBuilder({
Key? key,
Stream<T>? stream,
T? initialData,
required AsyncWidgetBuilder<T> builder,
})
複製程式碼
實際上,您需要建立一個 Stream 並將其作為流爭用傳遞。然後,在這一點上,您需要傳遞一個 AsyncWidgetBuilder,該 AsyncWidgetBuilder 可用於構造依賴於 Stream 快照的小部件。
引數:
下面是 StreamBuilderare 的一些引數:
Key? key
: 小部件的鍵,用於控制小部件如何被另一個小部件取代Stream<T>? stream
: 一個流,其快照可以通過生成器函式獲得T? initialData
: 將利用這些資料製作初始快照required AsyncWidgetBuilder<T> builder
: 生成過程由此生成器使用
如何實現 dart 檔案中的程式碼:
你需要分別在你的程式碼中實現它:
讓我們建立一個流:
下面的函式返回一個每秒生成一個數字的 Stream。你需要使用 async * 關鍵字來建立一個流。若要發出值,可以使用 yield 關鍵字後跟要發出的值。
Stream<int> generateNumbers = (() async* {
await Future<void>.delayed(Duration(seconds: 2));
for (int i = 1; i <= 10; i++) {
await Future<void>.delayed(Duration(seconds: 1));
yield i;
}
})();
複製程式碼
From that point onward, pass it as the stream argument
從那一點開始,把它作為流引數傳遞下去
StreamBuilder<int>(
stream: generateNumbers,
// other arguments
)
複製程式碼
讓我們建立一個 AsyncWidgetBuilder
建構函式期望您傳遞一個型別為 AsyncWidgetBuilder 的命名爭用構建器。這是一個有兩個引數的函式,它們的型別都是 BuildContext 和 AsyncSnapshot < t > 。後續的邊界(包含當前快照)可以用來確定應該呈現的內容。
要建立這個函式,首先需要了解 AsyncSnapshot。AsyncSnapshot 是使用非同步計算的最新通訊的不變描述。在這種獨特的情況下,它解決了與 Stream 的最新通訊。可以通過 AsyncSnapshot 屬性獲取流的最新快照。您可能需要使用的屬性之一是 connectionState,這個列舉將當前關聯狀態轉換為非同步計算,在這種特殊情況下,這種非同步計算就是 Steam。
StreamBuilder<int>(
stream: generateNumbers,
builder: (
BuildContext context,
AsyncSnapshot<int> snapshot,
) {
if (snapshot.connectionState == ConnectionState.waiting) {
return CircularProgressIndicator();
} else if (snapshot.connectionState == ConnectionState.active
|| snapshot.connectionState == ConnectionState.done) {
if (snapshot.hasError) {
return const Text('Error');
} else if (snapshot.hasData) {
return Text(
snapshot.data.toString(),
style: const TextStyle(color: Colors._red_, fontSize: 40)
);
} else {
return const Text('Empty data');
}
} else {
return Text('State: ${snapshot.connectionState}');
}
},
),
複製程式碼
AsyncSnapshot 還有一個名為 hasError 的屬性,可用於檢查快照是否包含非空錯誤值。如果非同步活動的最新結果失敗,hasError 值將有效。為了獲取資訊,首先,您可以通過獲取其 hasData 屬性來檢查快照是否包含資訊,如果 Stream 有效地釋放了任何非空值,那麼 hasData 屬性將是有效的。然後,在這一點上,您可以從 AsyncSnapshot 的資料屬性獲取資訊。
由於上面屬性的值,您可以計算出應該在螢幕上呈現什麼。在下面的程式碼中,當 connectionState 值正在等待時,將顯示一個 CircularProgressIndicator。當 connectionState 更改為 active 或 done 時,可以檢查快照是否有錯誤或資訊。建造函式稱為 Flutter 管道的檢測。因此,它將獲得一個與時間相關的快照子組。這意味著,如果在實際上相似的時間裡,Stream 發出了一些值,那麼一部分值可能沒有傳遞給構建器。
列舉有一些可能的值:
- > none: 無: 不與任何非同步計算關聯。如果流為空,則可能發生
- > waiting: 等待: 與非同步計算關聯並等待協作。在這個上下文中,它暗示流還沒有完成
- > active: 活躍的: 與活動的非同步計算相關聯。例如,如果一個 Stream 已經返回了任何值,但此時還沒有結束
- > done: > 完成: 與結束的非同步計算相關聯。在這個上下文中,它暗示流已經完成
設定初始資料:
您可以選擇傳遞一個 worth 作為 initialData 引數,這個引數將被利用,直到 Stream 發出 a。如果傳遞的值不為空,那麼當 connectionState 在等待時,hasData 屬性在任何事件中首先都將為 true
StreamBuilder<int>(
initialData: 0,
// other arguments
)
複製程式碼
要在 connectionState 等待時顯示初始資料,應該調整 if snapshot.connectionState = = connectionState.waiting,然後調整上面程式碼中的塊。
if (snapshot.connectionState == ConnectionState.waiting) {
return Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
CircularProgressIndicator(),
Visibility(
visible: snapshot.hasData,
child: Text(
snapshot.data.toString(),
style: const TextStyle(color: Colors._black_, fontSize: 24),
),
),
],
);
}
複製程式碼
當我們執行應用程式,我們應該得到螢幕的輸出像下面的螢幕視訊。
Code File:
密碼檔案:
import 'package:flutter/material.dart';
import 'package:flutter_steambuilder_demo/splash_screen.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Splash(),
debugShowCheckedModeBanner: false,
);
}
}
Stream<int> generateNumbers = (() async* {
await Future<void>.delayed(Duration(seconds: 2));
for (int i = 1; i <= 10; i++) {
await Future<void>.delayed(Duration(seconds: 1));
yield i;
}
})();
class StreamBuilderDemo extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return _StreamBuilderDemoState ();
}
}
class _StreamBuilderDemoState extends State<StreamBuilderDemo> {
@override
initState() {
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
automaticallyImplyLeading: false,
title: const Text('Flutter StreamBuilder Demo'),
),
body: SizedBox(
width: double._infinity_,
child: Center(
child: StreamBuilder<int>(
stream: generateNumbers,
initialData: 0,
builder: (
BuildContext context,
AsyncSnapshot<int> snapshot,
) {
if (snapshot.connectionState == ConnectionState.waiting) {
return Column(
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
CircularProgressIndicator(),
Visibility(
visible: snapshot.hasData,
child: Text(
snapshot.data.toString(),
style: const TextStyle(color: Colors._black_, fontSize: 24),
),
),
],
);
} else if (snapshot.connectionState == ConnectionState.active
|| snapshot.connectionState == ConnectionState.done) {
if (snapshot.hasError) {
return const Text('Error');
} else if (snapshot.hasData) {
return Text(
snapshot.data.toString(),
style: const TextStyle(color: Colors._red_, fontSize: 40)
);
} else {
return const Text('Empty data');
}
} else {
return Text('State: ${snapshot.connectionState}');
}
},
),
),
),
);
}
}
複製程式碼
結語:
在本文中,我已經簡單介紹了 StreamBuilder 的基本結構; 您可以根據自己的選擇修改這段程式碼。這是我對 StreamBuilder On User Interaction 的一個小小介紹,它正在使用 Flutter 工作。
© 貓哥
-
微信群 ducafecat
往期
開源
GetX Quick Start
新聞客戶端
strapi 手冊譯文
微信討論群 ducafecat
系列集合
譯文
開源專案
Dart 程式語言基礎
space.bilibili.com/404904528/c…
Flutter 零基礎入門
space.bilibili.com/404904528/c…
Flutter 實戰從零開始 新聞客戶端
space.bilibili.com/404904528/c…
Flutter 元件開發
space.bilibili.com/404904528/c…
Flutter Bloc
space.bilibili.com/404904528/c…
Flutter Getx4
space.bilibili.com/404904528/c…