更正 Flutter 应用中 StreamBuilder 的 Null Safety 问题
Correcting Null Safety issue with StreamBuilder in Flutter app
我的 flutter 应用程序中的 StreamBuilder 存在空安全问题。
在构建器的左括号“{”上:属性我收到此错误
正文可能会正常完成,导致 'null' 被 returned,但 return 类型可能是不可为 null 的类型。
这是 StreamBuilder 的代码。
StreamBuilder (
stream: _db.collection('agency').doc(globals.agencyId).
collection('trxns').doc(globals.currentTrxnId).snapshots(),
builder: (BuildContext context, AsyncSnapshot trxnSnapshot) {
if (trxnSnapshot.hasData) {
var outPut = (trxnSnapshot.data() as QueryDocumentSnapshot);
clientFNameController.text = trxnSnapshot.data.data['clientFName'] ?? "";
}
),
我尝试添加这样的类型:StreamBuilder (
但我收到此错误:参数类型 'Stream<DocumentSnapshot<Map<String, dynamic>>>' 无法分配给参数类型 'Stream<QuerySnapshot<Object?>>?'.
现在我更改类型以匹配上面的语句,现在我回到了原始错误消息。这是我将类型更改为。
StreamBuilder <DocumentSnapshot<Map<String, dynamic>>>(
stream: _db.collection('agency').doc(globals.agencyId).
collection('trxns').doc(globals.currentTrxnId).snapshots(),
builder: (BuildContext context, AsyncSnapshot trxnSnapshot) {
if (trxnSnapshot.hasData) {
var outPut = (trxnSnapshot.data() as QueryDocumentSnapshot);
clientFNameController.text = trxnSnapshot.data.data['clientFName'] ?? "";
}
),
我不知道出了什么问题或如何解决。我知道我需要这个“!”或这个 ”?”但我不知道该放哪一个或放在哪里。
非常感谢您的帮助。
StreamBuilder
必须在其 builder
参数中 return 一个 Widget。如果你不需要显示任何 Widget(只是做一些后台更新),你可以使用 StreamSubscription
代替:
class _MyWidgetState extends State<MyWidget> {
late final StreamSubscription<DocumentSnapshot> _subscription;
@override
void initState() {
super.initState();
final Stream<DocumentSnapshot> stream = _db
.collection('agency')
.doc(globals.agencyId)
.collection('trxns')
.doc(globals.currentTrxnId)
.snapshots();
_subscription = stream.listen((data) {
if (data == null) return;
setState(() => clientFNameController.text = data['clientFName'] ?? "");
});
}
@override
void dispose() {
_subscription.cancel();
super.dispose();
}
}
但是,如果您想继续使用 StreamBuilder
,您可以
- 只是 return 一个空的小部件(这不是一个好的做法):
StreamBuilder(
stream: _db
.collection('agency')
.doc(globals.agencyId)
.collection('trxns')
.doc(globals.currentTrxnId)
.snapshots(),
builder: (BuildContext context, AsyncSnapshot trxnSnapshot) {
if (trxnSnapshot.hasData) {
var outPut = (trxnSnapshot.data as QueryDocumentSnapshot);
clientFNameController.text = outPut.data['clientFName'] ?? "";
}
return SizedBox.shrink();
},
),
- return一个有意义的基于每个操作的Widget:
StreamBuilder(
stream: _db
.collection('agency')
.doc(globals.agencyId)
.collection('trxns')
.doc(globals.currentTrxnId)
.snapshots(),
builder: (BuildContext context, AsyncSnapshot trxnSnapshot) {
if (trxnSnapshot.hasData) {
var outPut = (trxnSnapshot.data as QueryDocumentSnapshot);
clientFNameController.text = outPut.data['clientFName'] ?? "";
return Text("client name updated");
}
return Text("client name not updated");
},
),
我的 flutter 应用程序中的 StreamBuilder 存在空安全问题。
在构建器的左括号“{”上:属性我收到此错误 正文可能会正常完成,导致 'null' 被 returned,但 return 类型可能是不可为 null 的类型。
这是 StreamBuilder 的代码。
StreamBuilder (
stream: _db.collection('agency').doc(globals.agencyId).
collection('trxns').doc(globals.currentTrxnId).snapshots(),
builder: (BuildContext context, AsyncSnapshot trxnSnapshot) {
if (trxnSnapshot.hasData) {
var outPut = (trxnSnapshot.data() as QueryDocumentSnapshot);
clientFNameController.text = trxnSnapshot.data.data['clientFName'] ?? "";
}
),
我尝试添加这样的类型:StreamBuilder ( 但我收到此错误:参数类型 'Stream<DocumentSnapshot<Map<String, dynamic>>>' 无法分配给参数类型 'Stream<QuerySnapshot<Object?>>?'.
现在我更改类型以匹配上面的语句,现在我回到了原始错误消息。这是我将类型更改为。
StreamBuilder <DocumentSnapshot<Map<String, dynamic>>>(
stream: _db.collection('agency').doc(globals.agencyId).
collection('trxns').doc(globals.currentTrxnId).snapshots(),
builder: (BuildContext context, AsyncSnapshot trxnSnapshot) {
if (trxnSnapshot.hasData) {
var outPut = (trxnSnapshot.data() as QueryDocumentSnapshot);
clientFNameController.text = trxnSnapshot.data.data['clientFName'] ?? "";
}
),
我不知道出了什么问题或如何解决。我知道我需要这个“!”或这个 ”?”但我不知道该放哪一个或放在哪里。
非常感谢您的帮助。
StreamBuilder
必须在其 builder
参数中 return 一个 Widget。如果你不需要显示任何 Widget(只是做一些后台更新),你可以使用 StreamSubscription
代替:
class _MyWidgetState extends State<MyWidget> {
late final StreamSubscription<DocumentSnapshot> _subscription;
@override
void initState() {
super.initState();
final Stream<DocumentSnapshot> stream = _db
.collection('agency')
.doc(globals.agencyId)
.collection('trxns')
.doc(globals.currentTrxnId)
.snapshots();
_subscription = stream.listen((data) {
if (data == null) return;
setState(() => clientFNameController.text = data['clientFName'] ?? "");
});
}
@override
void dispose() {
_subscription.cancel();
super.dispose();
}
}
但是,如果您想继续使用 StreamBuilder
,您可以
- 只是 return 一个空的小部件(这不是一个好的做法):
StreamBuilder(
stream: _db
.collection('agency')
.doc(globals.agencyId)
.collection('trxns')
.doc(globals.currentTrxnId)
.snapshots(),
builder: (BuildContext context, AsyncSnapshot trxnSnapshot) {
if (trxnSnapshot.hasData) {
var outPut = (trxnSnapshot.data as QueryDocumentSnapshot);
clientFNameController.text = outPut.data['clientFName'] ?? "";
}
return SizedBox.shrink();
},
),
- return一个有意义的基于每个操作的Widget:
StreamBuilder(
stream: _db
.collection('agency')
.doc(globals.agencyId)
.collection('trxns')
.doc(globals.currentTrxnId)
.snapshots(),
builder: (BuildContext context, AsyncSnapshot trxnSnapshot) {
if (trxnSnapshot.hasData) {
var outPut = (trxnSnapshot.data as QueryDocumentSnapshot);
clientFNameController.text = outPut.data['clientFName'] ?? "";
return Text("client name updated");
}
return Text("client name not updated");
},
),