如何快速将我的Firestore数据库数据加载到我的Flutter应用程序中?

huangapple go评论62阅读模式
英文:

How can I load my firestore database data quickly into my flutter application?

问题

我正在使用Flutter开发一个食谱应用程序。我有一个Firestore数据库,其中存储着我的食谱数据。

查看数据库:如何快速将我的Firestore数据库数据加载到我的Flutter应用程序中?

以下是我从数据库获取数据的方式:

  @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: 如何快速将我的Firestore数据库数据加载到我的Flutter应用程序中?.

This is how I am getting data from the database:

  @override
  void initState() {
    super.initState();
    getRecipeData();
  }

  Future&lt;void&gt; getRecipeData() async {
    WidgetsBinding.instance.addPostFrameCallback((_) async {
      showDialog(
        context: context,
        barrierDismissible: false,
        builder: (BuildContext context) {
          dialogContext = context;
          return ProgressBar(
            message: &quot;Loading..&quot;,
          );
        },
      );
    });
    int count = await RecipeModel().getRecipeCount();
    int recipeID = 101;
    for (int i = 0; i &lt; count; i++, recipeID++) {
      if (await RecipeModel().checkIfRecipeDocExists(recipeID.toString()) ==
          true) {
        recipeIDs.add(recipeID.toString());
        recipeDescription.add((await RecipeModel()
            .getRecipeData(recipeID.toString(), &#39;recipe_description&#39;))!);
        recipeName.add((await RecipeModel()
            .getRecipeData(recipeID.toString(), &#39;recipe_name&#39;))!);
        recipeURL.add((await RecipeModel()
            .getRecipeData(recipeID.toString(), &#39;recipeImageURL&#39;))!);
        recipeRating.add((await RecipeModel()
            .getRecipeData(recipeID.toString(), &#39;recipe_rating&#39;))!);
        recipeTime.add((await RecipeModel()
            .getRecipeData(recipeID.toString(), &#39;recipe_time&#39;))!);
        recipeIngredients.add((await RecipeModel()
            .getRecipeData(recipeID.toString(), &#39;recipe_ingredients&#39;))!);
      }
    }
    for (int i = 0; i &lt; 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&lt;String?&gt; getRecipeData(String recipeID, String key) async {
    try {
      CollectionReference recipes =
          FirebaseFirestore.instance.collection(&#39;recipes&#39;);
      final snapshot = await recipes.doc(recipeID).get();
      final data = snapshot.data() as Map&lt;String, dynamic&gt;;
      return data[key].toString();
    } catch (e) {
      return &#39;Error fetching user&#39;;
    }
  }

  Future&lt;int&gt; getRecipeCount() async {
    int count = await FirebaseFirestore.instance
        .collection(&#39;recipes&#39;)
        .get()
        .then((value) =&gt; value.size);
    return count;
  }

  Future&lt;bool&gt; checkIfRecipeDocExists(String recipeID) async {
    try {
      var collectionReference =
          FirebaseFirestore.instance.collection(&#39;recipes&#39;);
      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&lt;Map&lt;String, dynamic&gt;&gt; recipesSnapshot = firestore.collection(&#39;recipes&#39;).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(&#39;recipe_name&#39;),
            recipeDescription: doc.get(&#39;recipe_description&#39;),
...
      );
    }

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(&#39;recipe_name&#39;),
        ...
;

Then you could do it like this:

for(QueryDocumentSnapshot doc in recipesSnapshot.docs){
    recipes.add(Recipe.fromQueryDocumentSnapshot(doc));
        }

huangapple
  • 本文由 发表于 2023年2月8日 17:45:21
  • 转载请务必保留本文链接:https://go.coder-hub.com/75383889.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定