我的程序中有一个功能,我必须输入用户的详细信息,如用户的年龄、身高和体重。此数据将存储在Firestore中。
这是用户如何输入他们的详细信息
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import com.google.android.gms.tasks.OnFailureListener;
import com.google.android.gms.tasks.OnSuccessListener;
import com.google.android.material.button.MaterialButton;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.firestore.DocumentReference;
import com.google.firebase.firestore.FirebaseFirestore;
import org.jetbrains.annotations.NotNull;
import java.util.HashMap;
import java.util.Map;
public class account_information extends AppCompatActivity {
public static final String TAG = "TAG";
EditText et_age, et_height, et_weight;
Button btn_create;
FirebaseFirestore db;
FirebaseAuth mAuth;
String userID;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_account_information);
mAuth = FirebaseAuth.getInstance();
db = FirebaseFirestore.getInstance();
et_age = findViewById(R.id.et_age);
et_height = findViewById(R.id.et_height);
et_weight = findViewById(R.id.et_weight);
btn_create = findViewById(R.id.btn_create);
btn_create.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String age = et_age.getText().toString().trim();
String height = et_height.getText().toString().trim();
String weight = et_weight.getText().toString().trim();
if(age.isEmpty()){
et_age.setError("Age is mandatory");
et_age.requestFocus();
return;
}
if(height.isEmpty()){
et_height.setError("Height is mandatory");
et_height.requestFocus();
return;
}
if(weight.isEmpty()){
et_weight.setError("Weight is mandatory");
et_weight.requestFocus();
return;
}
userID = mAuth.getCurrentUser().getUid();
DocumentReference documentReference = db.collection("userDetail").document(userID);
Map<String,Object> user = new HashMap<>();
user.put("Age",age);
user.put("Height",height);
user.put("Weight",weight);
user.put("UserId", userID);
documentReference.set(user)
.addOnSuccessListener((OnSuccessListener) (aVoid) -> {
Log.d(TAG, "onSuccess: user Detail is created for "+ userID);
startActivity(new Intent(account_information.this, MainActivity.class));
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull @NotNull Exception e) {
Log.d(TAG, "onFailure"+ e.toString());
}
});
}
});
}
}
这是它将如何存储在firebase
https://i.stack.imgur.com/lBbN1.jpg
但是,当用户决定更新他们的配置文件(例如他的权重)时,其余的输入将在firebase
传递一个空字符串。:
https://i.stack.imgur.com/W8iIz.jpg
这是用户如何更新他们的详细信息
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import com.google.android.gms.tasks.OnFailureListener;
import com.google.android.gms.tasks.OnSuccessListener;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.firestore.DocumentReference;
import com.google.firebase.firestore.FirebaseFirestore;
import org.jetbrains.annotations.NotNull;
public class UpdateProfile extends AppCompatActivity {
public static final String TAG = "TAG";
EditText et_age, et_height, et_weight;
Button btn_update;
FirebaseAuth mAuth;
FirebaseFirestore mStore;
String userID;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_update_profile);
et_age = findViewById(R.id.et_age);
et_height = findViewById(R.id.et_height);
et_weight = findViewById(R.id.et_weight);
btn_update = findViewById(R.id.btn_update);
mAuth = FirebaseAuth.getInstance();
mStore = FirebaseFirestore.getInstance();
userID = mAuth.getCurrentUser().getUid();
btn_update.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String age = et_age.getText().toString().trim();
String height = et_height.getText().toString().trim();
String weight = et_weight.getText().toString().trim();
userID = mAuth.getCurrentUser().getUid();
DocumentReference documentReference = mStore.collection("userDetail").document(userID);
documentReference
.update("Age",age, "Height",height, "Weight",weight)
.addOnSuccessListener((OnSuccessListener) (aVoid) -> {
Log.d(TAG, "onSuccess: user Detail is created for "+ userID);
startActivity(new Intent(UpdateProfile.this, MainActivity.class));
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull @NotNull Exception e) {
Log.d(TAG, "onFailure"+ e.toString());
}
});
}
});
}}
更新:我已经尝试了@zen_of_kermit的方法,但我遇到了同样的问题,也许在代码中有一些东西,我错过了
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import com.google.android.gms.tasks.OnFailureListener;
import com.google.android.gms.tasks.OnSuccessListener;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.firestore.DocumentReference;
import com.google.firebase.firestore.FirebaseFirestore;
import org.jetbrains.annotations.NotNull;
import java.util.HashMap;
import java.util.Map;
public class UpdateProfile extends AppCompatActivity {
public static final String TAG = "TAG";
EditText et_age, et_height, et_weight;
Button btn_update;
FirebaseAuth mAuth;
FirebaseFirestore mStore;
String userID;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_update_profile);
et_age = findViewById(R.id.et_age);
et_height = findViewById(R.id.et_height);
et_weight = findViewById(R.id.et_weight);
btn_update = findViewById(R.id.btn_update);
mAuth = FirebaseAuth.getInstance();
mStore = FirebaseFirestore.getInstance();
userID = mAuth.getCurrentUser().getUid();
btn_update.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String age = et_age.getText().toString().trim();
String height = et_height.getText().toString().trim();
String weight = et_weight.getText().toString().trim();
userID = mAuth.getCurrentUser().getUid();
DocumentReference documentReference = mStore.collection("userDetail").document(userID);
Map<String, Object> dataToUpdateMap = new HashMap<>();
if (isValidAndChanged(documentReference, "Age", age)) {
dataToUpdateMap.put("Age", age);
}
if (isValidAndChanged(documentReference, "Height", height)) {
dataToUpdateMap.put("Height", height);
}
if (isValidAndChanged(documentReference, "Weight", weight)) {
dataToUpdateMap.put("Weight", weight);
}
documentReference.update(dataToUpdateMap).addOnSuccessListener((OnSuccessListener) (aVoid) -> {
Log.d(TAG, "onSuccess: user Detail is created for "+ userID);
startActivity(new Intent(UpdateProfile.this, readProfileData.class));
}).addOnFailureListener(new OnFailureListener() {
@Override
public void onFailure(@NonNull @NotNull Exception e) {
Log.d(TAG, "onFailure"+ e.toString());
}
});
}
});
}
boolean isValidAndChanged(DocumentReference docRef, String key, Object value) {
return true;
}
}
传递了所有三个字段(年龄、身高、体重),而没有检查它们是否有效或是否包含对现有数据的更改。您应该在调用update之前进行这些检查,类似于在create函数中所做的操作。
例如,创建一个函数来检查新数据是否有效,是否与旧数据不同:
boolean isValidAndChanged(DocumentReference docRef, String key, String value) {
// TODO get snapshot of data and compare to new value
}
然后使用它来更新(将Map
传递给update
而不是var-args):
String age = et_age.getText().toString().trim();
String height = et_height.getText().toString().trim();
String weight = et_weight.getText().toString().trim();
userID = mAuth.getCurrentUser().getUid();
DocumentReference documentReference = mStore.collection("userDetail").document(userID);
Map<String, String> dataToUpdateMap = new HashMap<>();
if (isValidAndChanged(documentReference, "Age", age)) {
dataToUpdateMap.put("Age", age);
}
if (isValidAndChanged(documentReference, "Height", height)) {
dataToUpdateMap.put("Height", height);
}
if (isValidAndChanged(documentReference, "Weight", weight)) {
dataToUpdateMap.put("Weight", weight);
}
documentReference.update(dataToUpdateMap)
// ...
此外,最佳实践是使用常量,而不是在代码中到处传递魔法字符串(例如"Age")变为AGE
)
您将覆盖所有数据,因为您将空字符串传递给update()方法。Firestore确实可以保存空值,但是更新后Age
和Height
的值不是空的,而是空字符串。
如果您想要更新单个字段而保持其他字段不变,那么您应该简单地将需要更新的字段的值传递给update()方法。在代码中,它应该是这样的:
documentReference.update("Weight", weight).addOnSuccessListener(/* ... /*);