通过1个Android Studio更新Firebase中的数据字段

时间:2018-05-21 08:30:05

标签: android firebase firebase-realtime-database

我正在尝试将 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




2 个答案:

答案 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) {

                    }
                });