У меня есть кнопка для переименования дочернего узла в базе данных firebase и editTextView для пользователей, чтобы ввести строку для имени нового дочернего узла. При нажатии кнопки строка будет извлечена из editTextView и будет использоваться для переименования дочернего узла.
В моем подходе к кодированию для переименования дочернего узла из имени пользователя "Paul" в имя пользователя "John" я хотел бы: (1) создать новый дочерний узел с именем "John" и (2) скопировать значения в Дочерний узел "Paul" переходит к дочернему узлу "John" и, наконец, (3) удаляет дочерний узел "Paul".
Коды, которые я написал, могут без проблем переименовать имя пользователя «Джон», но говорят, когда я хочу переименовать во второй раз новое имя пользователя с именем «Кен», при нажатой кнопке во второй раз , весь узел будет полностью уничтожен, что означает, что там ничего не осталось. Почему пропал дочерний узел «Кен» и как я могу исправить код?
Вот скриншоты консоли базы данных, объясняющие, что происходит при нажатии кнопки.
(Изображение 1) Это состояние до нажатия кнопки. Исходное имя пользователя: «Paul»:
(Рисунок 2). Это происходит при первом нажатии кнопки для переименования в «John». Коды функционируют без ошибок до этого момента:
(Рисунок 3) Это когда кнопка нажимается во второй раз, чтобы снова переименовать в «Ken». Коды не работают должным образом, и, к сожалению, все узлы удаляются, и «Кен» не появляется.
Вот фрагмент кода Я написал: Для записи, строковая переменная «username» - это существующее имя пользователя (здесь это «Paul»), строковая переменная «временное имя пользователя» - это новое имя (здесь это «John» на первой кнопке). нажата и должна быть "Кен" при нажатии второй кнопки). EditTextView, который является «usernameInputView», - это место, из которого извлекается строковая переменная «временное имя пользователя».
usernameSharedPreferences = getSharedPreferences("usernameSharedPreferences", Context.MODE_PRIVATE);
username = usernameSharedPreferences.getString("userName", "");
renameUserButton.setOnClickListener(new View.OnClickListener() {
if (username!=null && !username.equals("")) { //Check that the existing username isn't empty
String temporaryUsername = usernameInputView.getText().toString();
if (temporaryUsername!=null && !temporaryUsername.equals("")) {
// (1) Creatw a new child node (temporaryUsername)
mRootReference.child("Users' Input History").child(temporaryUsername).push().setValue("");
// (2) Copy the values from the exisiting node (username) to the new node (temporaryUsername)
DatabaseReference usersInputHistorySourceNode = FirebaseDatabase.getInstance().getReference().child("Users' Input History").child(username);
final DatabaseReference usersInputHistoryTargetNode = FirebaseDatabase.getInstance().getReference().child("Users' Input History").child(temporaryUsername);
ValueEventListener valueEventListenerForUsersInputHistory = new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
usersInputHistoryTargetNode.setValue(dataSnapshot.getValue()).addOnCompleteListener(new OnCompleteListener<Void>() {
@Override
public void onComplete(@NonNull Task<Void> task) {
if (task.isComplete()) {
Log.d("User Input History copy", "Success!");
} else {
Log.d("User Input History copy", "Copy failed!");
}
}
});
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {}
};
usersInputHistorySourceNode.addListenerForSingleValueEvent(valueEventListenerForUsersInputHistory);
// (3) Remove the existing node (username)
mChildReferenceForInputHistory.child(username).removeValue();
//Make "username" equal to "temporaryUsername" (meaning to make "temporaryUsername" as the new existing username) and save into SharedPreferences
usernameSharedPreferences = getSharedPreferences("usernameSharedPreferences", MODE_PRIVATE);
usernameSharedPreferences.edit().putString("userName", temporaryUsername).apply();
Toast.makeText(getApplicationContext(), getResources().getString(R.string.Your_new_username_is) + temporaryUsername, Toast.LENGTH_LONG).show();
}
else {
Toast.makeText(getApplicationContext(), R.string.You_have_not_entered_any_username, Toast.LENGTH_LONG).show();
}
}
else {
Toast.makeText(getApplicationContext(), R.string.You_have_not_entered_any_username, Toast.LENGTH_LONG).show();
}
});
Вот что я пробовал:
Я пытался принудительно запустить процесс переименования дважды. Я упаковал весь код в OnClickListener во вспомогательный метод renameNode () и дважды передал renameNode () в OnClickListener. Я подумал, что если второй раз не сработает, тогда я могу просто заставить его запустить процесс переименования в третий раз, но все же у меня ничего не получилось. При использовании этого метода в базе данных не появится даже ни одного узла (что идентично ситуации, показанной на рисунке 3 выше), поэтому я не в курсе. Ниже приведены точные коды:
String temporaryUsername;
renameUserButton.setOnClickListener(new View.OnClickListener() {
if (username!=null && !username.equals("")) { //Check that the existing username isn't empty
temporaryUsername = usernameInputView.getText().toString();
renameNode();
renameNode();
}
else {
Toast.makeText(getApplicationContext(), R.string.You_have_not_entered_any_username, Toast.LENGTH_LONG).show();
}
}
else {
Toast.makeText(getApplicationContext(), R.string.You_have_not_entered_any_username, Toast.LENGTH_LONG).show();
}
});
public void renameNode() {
if (temporaryUsername!=null && !temporaryUsername.equals("")) {
// (1) Creatw a new child node (temporaryUsername)
mRootReference.child("Users' Input History").child(temporaryUsername).push().setValue("");
// (2) Copy the values from the exisiting node (username) to the new node (temporaryUsername)
DatabaseReference usersInputHistorySourceNode = FirebaseDatabase.getInstance().getReference().child("Users' Input History").child(username);
final DatabaseReference usersInputHistoryTargetNode = FirebaseDatabase.getInstance().getReference().child("Users' Input History").child(temporaryUsername);
ValueEventListener valueEventListenerForUsersInputHistory = new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
usersInputHistoryTargetNode.setValue(dataSnapshot.getValue()).addOnCompleteListener(new OnCompleteListener<Void>() {
@Override
public void onComplete(@NonNull Task<Void> task) {
if (task.isComplete()) {
Log.d("User Input History copy", "Success!");
} else {
Log.d("User Input History copy", "Copy failed!");
}
}
});
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {}
};
usersInputHistorySourceNode.addListenerForSingleValueEvent(valueEventListenerForUsersInputHistory);
// (3) Remove the existing node (username)
mChildReferenceForInputHistory.child(username).removeValue();
//Make "username" equal to "temporaryUsername" (meaning to make "temporaryUsername" as the new existing username) and save into SharedPreferences
usernameSharedPreferences = getSharedPreferences("usernameSharedPreferences", MODE_PRIVATE);
usernameSharedPreferences.edit().putString("userName", temporaryUsername).apply();
Toast.makeText(getApplicationContext(), getResources().getString(R.string.Your_new_username_is) + temporaryUsername, Toast.LENGTH_LONG).show();
}
(ОТВЕТ) Эта проблема решается с помощью Хагана Азизова.
Я поставил "mChildReferenceForInputHistory" .child (username) .removeValue () "в неправильной позиции и должен переместить ее на одну строку выше" Log.d ("Копия истории ввода пользователя", "Success!") ".
Так вот кусок кодов после исправления:
DatabaseReference usersInputHistorySourceNode = FirebaseDatabase.getInstance().getReference().child("Users' Input History").child(username);
final DatabaseReference usersInputHistoryTargetNode = FirebaseDatabase.getInstance().getReference().child("Users' Input History").child(temporaryUsername);
ValueEventListener valueEventListenerForUsersInputHistory = new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
usersInputHistoryTargetNode.setValue(dataSnapshot.getValue()).addOnCompleteListener(new OnCompleteListener<Void>() {
@Override
public void onComplete(@NonNull Task<Void> task) {
if (task.isComplete()) {
**// (3) Remove the existing node (username)
mChildReferenceForInputHistory.child(username).removeValue();**
Log.d("User Input History copy", "Success!");
} else {
Log.d("User Input History copy", "Copy failed!");
}
}
});
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {}
};
usersInputHistorySourceNode.addListenerForSingleValueEvent(valueEventListenerForUsersInputHistory);
Также я хотел бы поблагодарить GrahamD за указание мне правильного направления во избежание повреждения данных.