英文:
How can I load my firestore database data quickly into my flutter application?
问题
我正在使用Flutter开发一个食谱应用程序。我有一个Firestore数据库,其中存储着我的食谱数据。
查看数据库:。
以下是我从数据库获取数据的方式:
@override
void initState() {
super.initState();
getRecipeData();
}
Future<void> getRecipeData() async {
WidgetsBinding.instance.addPostFrameCallback((_) async {
showDialog(
context: context,
barrierDismissible: false,
builder: (BuildContext context) {
dialogContext = context;
return ProgressBar(
message: "Loading..",
);
},
);
});
int count = await RecipeModel().getRecipeCount();
int recipeID = 101;
for (int i = 0; i < count; i++, recipeID++) {
if (await RecipeModel().checkIfRecipeDocExists(recipeID.toString()) ==
true) {
recipeIDs.add(recipeID.toString());
recipeDescription.add((await RecipeModel()
.getRecipeData(recipeID.toString(), 'recipe_description'))!);
recipeName.add((await RecipeModel()
.getRecipeData(recipeID.toString(), 'recipe_name'))!);
recipeURL.add((await RecipeModel()
.getRecipeData(recipeID.toString(), 'recipeImageURL'))!);
recipeRating.add((await RecipeModel()
.getRecipeData(recipeID.toString(), 'recipe_rating'))!);
recipeTime.add((await RecipeModel()
.getRecipeData(recipeID.toString(), 'recipe_time'))!);
recipeIngredients.add((await RecipeModel()
.getRecipeData(recipeID.toString(), 'recipe_ingredients'))!);
}
}
for (int i = 0; i < recipeIDs.length; i++) {
recipes.add(
Recipes(
recipeID: recipeIDs[i],
recipeName: recipeName[i],
recipeDescription: recipeDescription[i],
recipeIngredients: [recipeIngredients[i]],
recipeRating: recipeRating[i],
recipeTime: recipeTime[i],
recipeURL: recipeURL[i]),
);
}
Navigator.pop(dialogContext!);
}
这是我的RecipeModel类:
class RecipeModel {
Future<String?> getRecipeData(String recipeID, String key) async {
try {
CollectionReference recipes =
FirebaseFirestore.instance.collection('recipes');
final snapshot = await recipes.doc(recipeID).get();
final data = snapshot.data() as Map<String, dynamic>;
return data[key].toString();
} catch (e) {
return 'Error fetching user';
}
}
Future<int> getRecipeCount() async {
int count = await FirebaseFirestore.instance
.collection('recipes')
.get()
.then((value) => value.size);
return count;
}
Future<bool> checkIfRecipeDocExists(String recipeID) async {
try {
var collectionReference =
FirebaseFirestore.instance.collection('recipes');
var doc = await collectionReference.doc(recipeID).get();
return doc.exists;
} catch (e) {
rethrow;
}
}
}
我不知道为什么加载数据要花大约10-15秒的时间。是否有其他加载数据的方式?目前只有测试数据,以后数据将增加到500多个食谱,请根据此情况给予建议。谢谢。
我正在考虑将我的数据库从Firestore迁移到MongoDB,因为我对它一无所知,所以我倾向于寻求社区的帮助。
英文:
I am working on a recipe application on flutter. I have firestore database where my recipes data is stored.
Take a look at the database: .
This is how I am getting data from the database:
@override
void initState() {
super.initState();
getRecipeData();
}
Future<void> getRecipeData() async {
WidgetsBinding.instance.addPostFrameCallback((_) async {
showDialog(
context: context,
barrierDismissible: false,
builder: (BuildContext context) {
dialogContext = context;
return ProgressBar(
message: "Loading..",
);
},
);
});
int count = await RecipeModel().getRecipeCount();
int recipeID = 101;
for (int i = 0; i < count; i++, recipeID++) {
if (await RecipeModel().checkIfRecipeDocExists(recipeID.toString()) ==
true) {
recipeIDs.add(recipeID.toString());
recipeDescription.add((await RecipeModel()
.getRecipeData(recipeID.toString(), 'recipe_description'))!);
recipeName.add((await RecipeModel()
.getRecipeData(recipeID.toString(), 'recipe_name'))!);
recipeURL.add((await RecipeModel()
.getRecipeData(recipeID.toString(), 'recipeImageURL'))!);
recipeRating.add((await RecipeModel()
.getRecipeData(recipeID.toString(), 'recipe_rating'))!);
recipeTime.add((await RecipeModel()
.getRecipeData(recipeID.toString(), 'recipe_time'))!);
recipeIngredients.add((await RecipeModel()
.getRecipeData(recipeID.toString(), 'recipe_ingredients'))!);
}
}
for (int i = 0; i < recipeIDs.length; i++) {
recipes.add(
Recipes(
recipeID: recipeIDs[i],
recipeName: recipeName[i],
recipeDescription: recipeDescription[i],
recipeIngredients: [recipeIngredients[i]],
recipeRating: recipeRating[i],
recipeTime: recipeTime[i],
recipeURL: recipeURL[i]),
);
}
Navigator.pop(dialogContext!);
}
This is my recipeModel class:
class RecipeModel {
Future<String?> getRecipeData(String recipeID, String key) async {
try {
CollectionReference recipes =
FirebaseFirestore.instance.collection('recipes');
final snapshot = await recipes.doc(recipeID).get();
final data = snapshot.data() as Map<String, dynamic>;
return data[key].toString();
} catch (e) {
return 'Error fetching user';
}
}
Future<int> getRecipeCount() async {
int count = await FirebaseFirestore.instance
.collection('recipes')
.get()
.then((value) => value.size);
return count;
}
Future<bool> checkIfRecipeDocExists(String recipeID) async {
try {
var collectionReference =
FirebaseFirestore.instance.collection('recipes');
var doc = await collectionReference.doc(recipeID).get();
return doc.exists;
} catch (e) {
rethrow;
}
}
}
I don't know Why it take around 10-15seconds to just load the data in the application? Is there anyother way I can use to load the data? Right now I have just a test data later this data will be increased to 500+ recipes so that please suggest me according to that. Thankyou.
I am thinking to shift my database from firestore to mongoDB since I have no knowledge about it so I prefer to take help from the community.
答案1
得分: 2
正如Loc所提到的,每次查询都获取一个食谱可能是性能慢的原因。
我只会翻译代码哦。
英文:
as mentioned by Loc, fetching each recipe in its own query is probably the cause of the slow performance.
I'd get all the recipes by just fetching the entire collection once and then handle the data transfer from there on.
So something like this:
QuerySnapshot<Map<String, dynamic>> recipesSnapshot = firestore.collection('recipes').get();
for(QueryDocumentSnapshot doc in recipesSnapshot.docs){
// now do stuff with the data like recipes.add(Recipe.fromMap(doc.data! as Map);
}
This should reduce the runtime.
To answer your commented question you can do something like this:
for(QueryDocumentSnapshot doc in recipesSnapshot.docs){
recipes.add(Recipes(
recipeID: doc.id,
recipeName: doc.get('recipe_name'),
recipeDescription: doc.get('recipe_description'),
...
);
}
So just doc.get(FIREBASE_FIELD)
Alternatively you could use doc.data() as Map
to get the whole doc as a Map and then access its content like any other map.
If you want to be fancy and have to load recipes in different parts of your app you could also add a function like this to your recipe class (I did not check if this works, but it should):
Recipe.fromQueryDocumentSnapshot(QueryDocumentSnapshot snap)
: recipeID = snap.id,
recipeName = snap.get('recipe_name'),
...
;
Then you could do it like this:
for(QueryDocumentSnapshot doc in recipesSnapshot.docs){
recipes.add(Recipe.fromQueryDocumentSnapshot(doc));
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论