首页 > 解决方案 > Android Java Firebase 像地图一样保存数据

问题描述

我正在尝试将我的用户指向我的火力基地。这张图就是我想要的。

预期的数据库结构

我想添加我的用户结果,如地图。这是我如何调用我的方法下面的代码。

checkUserScoreIsExist(gameUser, new UserExistsCallback() {
    @Override
    public void onCallback(boolean isExisting) {
        saveUserScoreToFirebase(gameUser, currentGame, isExisting, 
            new ScoreUserCallback() {
                @Override
                  public void onCallback(boolean isScoreUserSaveSuccess) {
                      if(isScoreUserSaveSuccess)
                          Toast.makeText(GameActivity.this, "Score saved successfully", Toast.LENGTH_LONG).show();
                      else
                          Toast.makeText(GameActivity.this, "Score can not  saved successfully", Toast.LENGTH_LONG).show();
                  }
            });
     }
});

这些是我的方法。

private void checkUserScoreIsExist(final User user, final UserExistsCallback callback) {
    Log.d(TAG, "User score checking.");

    FirebaseFirestore rootRef = FirebaseFirestore.getInstance();
    DocumentReference docIdRef = rootRef.collection("scores").document(user.getUsername());
    docIdRef.get().addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() {
        @Override
        public void onComplete(@NonNull Task<DocumentSnapshot> task) {
            if (task.isSuccessful()) {
                DocumentSnapshot document = task.getResult();
                assert document != null;
                isScoreExist = document.exists();
            } else {
                Log.d(TAG, "Failed with: ", task.getException());
            }
            callback.onCallback(isScoreExist);
        }
    });
}

private void saveUserScoreToFirebase(User user, Game game, boolean isScoreExist, final ScoreUserCallback callback) {

    Log.d(TAG, "Saving user to database.");

    Map<String, Object> gameMap = new HashMap<>();
    gameMap.put("gameResult", game.calculateResult());

    if(isScoreExist){

        db.collection("scores").document(user.getUsername())
                .update(gameMap).addOnCompleteListener(new OnCompleteListener<Void>() {
            @Override
            public void onComplete(@NonNull Task<Void> task) {
                isSaveScoreSuccess = task.isSuccessful();
                callback.onCallback(isSaveScoreSuccess);
            }
        });

    }else{

        db.collection("scores").document(user.getUsername())
                .set(gameMap).addOnCompleteListener(new OnCompleteListener<Void>() {
            @Override
            public void onComplete(@NonNull Task<Void> task) {
                isSaveScoreSuccess = task.isSuccessful();
                callback.onCallback(isSaveScoreSuccess);
            }
        });

    }

当我这样尝试时,我无法保存我的新结果,它将被覆盖。我怎样才能获得像我的形象一样的数据库。请帮助我如何做到这一点。非常感谢大家。

标签: androidfirebasegoogle-cloud-firestore

解决方案


问题是,为了保持您记住的结构,您必须将整个文档更新到 Firestore。

因此,在更新分数时,您的应用程序的理想流程应该是执行 aget()以获取已作为地图存在的完整文档,将新分数添加到地图中,然后对其进行更新。您可以通过将saveUserScoreToFirebase函数更改为以下内容来做到这一点:


编辑:根据我们在聊天中的对话,您还想向该集合添加一个额外的字段,称为 gameTime,并且您有一个获取游戏模型对象的函数,该对象包含 gameResults 和 gameTime,并使其到一个 json 中,这简化了我们的生活,因为您需要做的就是在更新之前将该 json 添加到地图中。请注意,我之前提出的所有观点仍然有效,因此代码将如下所示:

private void saveUserScoreToFirebase(User user, Game game, boolean isScoreExist, final ScoreUserCallback callback) {

    Log.d(TAG, "Saving user to database.");

    Map<String, Object> gameMap = new HashMap<>();

    if(isScoreExist){

        db.collection("scores").document(user.getUsername())
          .get().addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() {
              @Override
              public void onComplete(@NonNull Task<DocumentSnapshot> task) {
                  if (task.isSuccessful()) {
                      // Document found in the offline cache
                      DocumentSnapshot document = task.getResult();
                      gameMap = document.getData();
                      // if you are starting with # 0 you can take the '+1' from this
                      gameMap.put(String.valueOf(gameMap.size()+1), game.toJSON());
                      db.collection("scores").document(user.getUsername())
                        .update(gameMap).addOnCompleteListener(new OnCompleteListener<Void>() {
                            @Override
                            public void onComplete(@NonNull Task<Void> task) {
                                isSaveScoreSuccess = task.isSuccessful();
                                callback.onCallback(isSaveScoreSuccess);
                            }
                      });
                  } else {
                    Log.d(TAG, "Getting previous score failed with following exception: ", task.getException());
                  }
              }
        });

    }else{

        gameMap.put(String.valueOf(gameMap.size()+1), game.toJSON());

        db.collection("scores").document(user.getUsername())
                .set(gameMap).addOnCompleteListener(new OnCompleteListener<Void>() {
            @Override
            public void onComplete(@NonNull Task<Void> task) {
                isSaveScoreSuccess = task.isSuccessful();
                callback.onCallback(isSaveScoreSuccess);
            }
        });

    }
}

注意:这是未经测试的,但如果它不能立即工作,应该是您考虑前面描述的逻辑的一个很好的起点。


推荐阅读