我有一個 FutureBuilder,它正在從我的 firebase 實時資料庫中獲取資料。結果應該是所有帖子的串列,它也可以作業,但只有一秒鐘左右,它會因為任何原因更新兩次,然后第二次資料又消失了。這是我的請求代碼:
Future<List<Posts>> getpostsOfThread() async {
List<String> threads = [];
await database
.ref()
.child("users/")
.child(user!.uid)
.child("threadsFollowing")
.once()
.then((value) => {
value.snapshot.children.forEach((element) {
threads.add(element.value.toString());
})
});
List<Posts> posts = [];
threads.forEach((element) async {
print("?");
await database
.ref()
.child("SecretChat")
.child("threads")
.child(element)
.child("posts")
.once()
.then((value) => {
value.snapshot.children.forEach((element) async {
posts.add(Posts(
postID: element.key.toString(),
title: element.child("title").value.toString(),
likes: int.parse(element.child("likes").value.toString()),
picturePath:
element.child("picturePath").value.toString()));
})
});
});
return posts;
}
這里是 FutureBuilder 的代碼:
Container(
decoration: BoxDecoration(
color: Color.fromRGBO(247, 241, 236, 1),
borderRadius: BorderRadius.only(
topLeft: Radius.circular(30),
topRight: Radius.circular(30))),
height: height * 0.7379,
child: SafeArea(
minimum: EdgeInsets.all(20),
child: (Container(
child: Center(
child: Column(children: [
//Text(massages.toString()),
Flexible(
child: FutureBuilder(
future: getpostsOfThread(),
builder: (BuildContextcontext,
AsyncSnapshot<List<Posts>> snapshot) {
print(snapshot.data);
if (snapshot.hasData) {
int lenght = snapshot.data!.length;
print(lenght);
return Container(
child: ListView.builder(
itemCount: lenght,
itemBuilder: (context, index) {
return Container(
child: Text(
snapshot.data![index].likes.toString()),
);
},
));
}
return Container();
}))
]))))))
uj5u.com熱心網友回復:
通常有兩種方法可以等待 Future 的結果。
(1) myFuture.then((值) {});
(2) 等待我的Future();
使用方法 (1) 時,代碼序列將在呼叫后繼續,當 Future 完成時,then()方法觸發并且該代碼運行。
例如:
myMethod() {
myFuture.then((value) { console.log("myFuture Finished"); });
console.log("myMethod Finished");
}
在這里,您應該在“myFuture Finished”之前看到“myMethod Finished”列印到控制臺。
當您需要等待未來完成后再繼續下一個代碼序列時,您可以使用await關鍵字。
myMethod() async {
await myFuture();
console.log("myMethod Finished");
}
有了這個例子。“myMethod Finished”只會在 Future 方法完成后出現在控制臺中。
您還應該知道,創建forEachList 的方法與呼叫 Future 方法非常相似,因為后面的代碼將在 forEach 回圈迭代時繼續執行。當需要為回圈的每次迭代等待來自 Future 的資料時,您將需要使用不同的語法。我經常回退,for(int i = 0; i < list.length; i ) {}因為它一直對我有用。
有了這些資訊,我已經修改了您的代碼以利用await關鍵字并確保該getpostsOfThread()方法僅在其中的所有代碼完成處理后才回傳,這應確保回傳執行緒和帖子。這是我想出的:
Future<List<Posts>> getpostsOfThread() async {
// assign the result to a variable
var value = await database
.ref()
.child("users/")
.child(user!.uid)
.child("threadsFollowing")
.once();
// simplify mapping the results to the threads
List<String> threads = value.snapshot.children.map((element) => element.value.toString()).toList();
List<Posts> posts = [];
// don't use .forEeach with an async
// instead use a loop that can take advantage of the existing async
for(int i = 0; i < threads.length; i ) {
// assign the result for this thread to a variable
var value2 = await database
.ref()
.child("SecretChat")
.child("threads")
.child(threads[i])
.child("posts")
.once();
// without async, loop results and create Posts
value2.snapshot.children.forEach((element) {
posts.add(Posts(
postID: element.key.toString(),
title: element.child("title").value.toString(),
likes: int.parse(element.child("likes").value.toString()),
picturePath:
element.child("picturePath").value.toString()));
});
}
// finally return the list of Posts
return posts;
}
請記住,這段代碼做了很多假設并且不會檢查任何錯誤。我建議在適當的地方添加錯誤檢查/捕獲以避免意外崩潰。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/412221.html
標籤:
