我正在尝试将 daysOnWhichPresent
字段的值更新为Firebase数据库中的1。在更新daysOnWhichPresent
的值之前和之后,我已经两次读取了该值,但它没有正确地从数据库中读取。在第一次读取时,该值应为6,但在获取数据后,其值为0.
此代码也不允许我更新daysOnWhichPresent
的值,
权限设置为对所有人进行读/写。
请帮帮我。
以下是Firebase数据库树
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;
import android.widget.Toast;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.ValueEventListener;
public class AttendanceActivity extends AppCompatActivity {
FirebaseDatabase firebaseDatabase;
DatabaseReference databaseReference;
String uniqueVolunteerId;
long daysPresent;
TextView textAttendance;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_attendance);
Bundle bundle = getIntent().getExtras();
uniqueVolunteerId = bundle.getString("uniqueVolunteerId");
Log.i("TAG", uniqueVolunteerId);
firebaseDatabase = FirebaseDatabase.getInstance();
databaseReference = firebaseDatabase.getReference("volunteers").child(uniqueVolunteerId);
textAttendance = findViewById(R.id.text_attendance);
databaseReference.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
daysPresent = dataSnapshot.child("daysOnWhichPresent").getValue(Long.class);
}
@Override
public void onCancelled(DatabaseError databaseError) {
Log.i("TAG", "Error in data fetching from server 1");
}
});
Log.i("TAG", Long.toString(daysPresent));
databaseReference.child("daysOnWhichPresent").setValue(daysPresent+1);
databaseReference.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
daysPresent = dataSnapshot.child("daysOnWhichPresent").getValue(Long.class);
Log.i("TAG", Long.toString(daysPresent));
textAttendance.setText(Long.toString(daysPresent));
Toast.makeText(getApplicationContext(), Long.toString(daysPresent), Toast.LENGTH_LONG).show();
}
@Override
public void onCancelled(DatabaseError databaseError) {
Log.i("TAG", "Error in data fetching from server 1");
}
});
}
}

日志显示daysPresent的值为0,1和6 但它应该是6,7和7。 请帮帮我。
根据Alex Mamo的建议,我已将代码更改为以下内容......
package com.aayush.reboot.nssnitdurgapur;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;
import com.google.firebase.database.DataSnapshot;
import com.google.firebase.database.DatabaseError;
import com.google.firebase.database.DatabaseReference;
import com.google.firebase.database.FirebaseDatabase;
import com.google.firebase.database.MutableData;
import com.google.firebase.database.Transaction;
import com.google.firebase.database.ValueEventListener;
import java.util.HashMap;
public class AttendanceActivity extends AppCompatActivity {
String uniqueVolunteerId;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_attendance);
Bundle bundle = getIntent().getExtras();
uniqueVolunteerId = bundle.getString("uniqueVolunteerId");
incrementAttendanceByOne(uniqueVolunteerId);
DatabaseReference volunteerRef = FirebaseDatabase.getInstance().getReference("volunteers").child(uniqueVolunteerId).child("daysOnWhichPresent");
volunteerRef.addValueEventListener(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
Long daysPresent = dataSnapshot.getValue(Long.class);
Log.i("TAG", "Value of daysOnWhichPresent in onCreate method "+ Long.toString(daysPresent));
}
@Override
public void onCancelled(DatabaseError databaseError) {
}
});
}
private void incrementAttendanceByOne(String uniqueVolunteerId) {
Log.i("TAG", "Unique ID: "+uniqueVolunteerId);
DatabaseReference volunteerRef = FirebaseDatabase.getInstance().getReference("volunteers").child(uniqueVolunteerId);
DatabaseReference daysPresentRef = volunteerRef.child("daysOnWhichPresent");
daysPresentRef.runTransaction(new Transaction.Handler() {
@Override
public Transaction.Result doTransaction(MutableData mutableData) {
Long daysPresent = mutableData.getValue(Long.class);
if (daysPresent == null) {
Log.i("TAG", "Days Present is null---"+Long.toString(daysPresent));
return Transaction.success(mutableData);
}
Log.i("TAG", "Old value in function incrementAttendanceByOne "+Long.toString(daysPresent));
mutableData.setValue(daysPresent+1);
daysPresent = mutableData.getValue(Long.class);
Log.i("TAG", "Updated value in function incrementAttendanceByOne "+Long.toString(daysPresent));
return Transaction.success(mutableData);
}
@Override
public void onComplete(DatabaseError databaseError, boolean b, DataSnapshot dataSnapshot) {
}
});
}
}

我在执行交易之前和之后打印了daysOnWhichPresent
值,显示了正确的结果。
但是当我在' onCreate()'中打印价值时执行incrementAttendanceByOne()
单个日志语句后的方法是给我两个值,首先更新一个值,然后更新旧值,这表示数据已在数据库中更改了一会儿,并再次恢复到之前的值。
问题应该是什么以及如何解决这个问题?
这是Logcat
05-22 10:51:44.000 22737-22737/com.aayush.reboot.nssnitdurgapur I/TAG: Unique ID: G8ho4gth5ZPU7z8Sk9uK40QbGtq1
05-22 10:51:44.010 22737-22811/com.aayush.reboot.nssnitdurgapur I/TAG: Old value in function incrementAttendanceByOne 25 Updated value in function incrementAttendanceByOne 26
05-22 10:51:44.066 22737-22737/com.aayush.reboot.nssnitdurgapur I/TAG: Value of daysOnWhichPresent in onCreate method 26
05-22 10:51:44.645 22737-22737/com.aayush.reboot.nssnitdurgapur I/TAG: Value of daysOnWhichPresent in onCreate method 25

答案 0 :(得分:0)
要解决此问题,您肯定需要使用Firebase Transactions。
处理可能因并发修改而损坏的数据(例如增量计数器)时,您可以使用事务操作。
为实现这一目标,请使用我在 post 中的回答,其中我已解释了如何在Firebase Realtime数据库中增加值以及如何将其读回。
您还需要知道您现在还不能使用尚未加载的内容。换句话说,您不能简单地在daysPresent
方法之外使用onDataChange()
对象,因为此方法的异步行为始终为null
。这意味着,当您尝试在该方法之外使用该结果时,数据尚未从数据库中完成加载,这就是为什么无法访问,并且您总是得到zero
快速解决此问题的方法是仅在daysPresent
方法中使用onDataChange()
,或者如果您想在外面使用它,我建议您深入了解异步世界并查看最后一部分我的anwser来自 post ,其中我已经解释了如何使用自定义回调来完成它。您还可以查看此 video ,以便更好地理解。
答案 1 :(得分:0)
我认为您应首先获得节点的正确值,然后在将其递增1后再更新。
请尝试以下方式:
yourChildRef.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
if (dataSnapshot != null) {
String toUserCounts = String.valueOf(dataSnapshot.getValue() == null ? "0" : dataSnapshot.getValue()); // Fetch value of node
Log.e("day value:" , toUserCounts); // Print value of node
HashMap<String, Object> params = new HashMap<>();
params.put("daysOnWhichPresent", Integer.parseInt(toUserCounts)+1); // increment daysOnWhichPresent by 1
yourDatabaseChildReference.updateChildren(params); // Update value on node
}
}
@Override
public void onCancelled(DatabaseError databaseError) {
}
});