我正在將資料從 Firestore 添加到Streamfrom StreamBuilder,但出現以下錯誤:
發生例外。StateError(壞狀態:快照既沒有資料也沒有錯誤
我的代碼。
class Home extends StatefulWidget {
const Home({Key? key}) : super(key: key);
@override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home> {
AppState? estado;
static String? userID = FirebaseAuth.instance.currentUser?.uid;
static final userColeccion = FirebaseFirestore.instance.collection("users");
var groupfav = ' ';
Stream<QuerySnapshot>? taskGroup;
@override
void initState() {
super.initState();
getGroupFavData();
}
void getGroupFavData() async {
var groupFavData = await userColeccion.doc("$userID").get();
var groupfav = groupFavData.data()!['groupfav'];
taskGroup = FirebaseFirestore.instance
.collection("groups")
.doc(groupfav) // pass the obtained value
.collection("task")
.snapshots();
}
@override
Widget build(BuildContext context) {
estado = Provider.of<AppState>(context, listen: true);
return Scaffold(
appBar: AppBar(
title: const Text("Home"),
automaticallyImplyLeading: false,
),
body: StreamBuilder(
stream: taskGroup,
builder: (
BuildContext context,
AsyncSnapshot<QuerySnapshot> snapshot,
) {
if (snapshot.hasError) {
return const Text("error");
}
if (snapshot.connectionState == ConnectionState.waiting) {
return const Text("Loading");
}
var data = snapshot.requireData;
return ListView.builder(
itemCount: data.size,
itemBuilder: (context, index) {
return Card(
child: ListTile(
title: Text("${data.docs[index]['titulo']}"),
subtitle: Text("${data.docs[index]['contenido']}"),
onTap: () {},
trailing: IconButton(
icon: const Icon(Icons.delete),
color: Colors.red[200],
onPressed: () {},
),
),
);
},
);
},
),
);
}
}
uj5u.com熱心網友回復:
好的,看看你的問題,我知道 1)你需要在開始監聽該檔案之前獲取檔案的資料,這很正常,所以你想先呼叫集合,獲取檔案,然后監聽名為task的檔案集合,這是有道理的。您的問題仍然是異步問題。該應用程式正在重建尚未到達的流;你必須修復事情的順序。
然后,您需要稍微改變一下并執行以下操作:
選項#1:a)使用FutureBuilder:這將允許您進行異步呼叫以根據用戶ID獲取檔案名稱b)在獲得與該用戶關聯的檔案后,您想監聽由產生的流該集合在該檔案中稱為任務。在那里你可以連接StreamBuilder。
選項#2 : a) 保持原樣,但聽任務組快照;但隨著值到達該集合,請繼續重建串列。
這些是我的建議。
這是選項1的一些簡短代碼:
// .. in your Scaffold's body:
Scaffold(
body: FutureBuilder( // the future builder fetches the initial data
future: userColeccion.doc("$userID").get(),
builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
if (snapshot.hasData) {
var groupfav = snapshot.data()!['groupfav'];
// then once the 'groupfav' has arrived,
// start listening on the taskGroup
taskGroup = FirebaseFirestore.instance
.collection("groups")
.doc(groupfav) // pass the obtained value
.collection("task")
.snapshots();
return StreamBuilder(
stream: taskGroup,
builder: (BuildContext context, AsyncSnapshot<QuerySnapshot> snapshot) {
// the rest of your code
});
}
return CircularProgressIndicator();
}
)
)
選項 2 類似于:
List<Task> userTasks = [];
void getGroupFavData() async {
var groupFavData = await userColeccion.doc("$userID").get();
var groupfav = groupFavData.data()!['groupfav'];
taskGroup = FirebaseFirestore.instance
.collection("groups")
.doc(groupfav) // pass the obtained value
.collection("task")
.snapshots().listen((snapshot) {
// here populate a list of your tasks
// and trigger a widget rebuild once you've grabbed the values
// and display it as a list on the UI
setState(() {
userTasks = snapshot.docs.map((d) => Task.fromJson(d.data())).toList();
});
});
}
And in your Scaffold, you can have a ListView just rendering the items on that task list, like:
ListView.builder(
itemCount: userTasks.length,
itemBuilder: (context, index) {
// render your tasks here
})
Here's a 
Hope those pointers take you somewhere.
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/439614.html
