Обновление поля данных в Firebase на 1 Android Studio - PullRequest
0 голосов
/ 21 мая 2018

Я пытаюсь обновить значение поля daysOnWhichPresent на 1 из базы данных Firebase.Здесь я прочитал значение два раза до и после обновления значения 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. Пожалуйста, помогите мне.

Какпредложенный Алексом Мамо, я изменил код следующим образом ...

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() один оператор log дает мне два значения, сначала обновляемое одно, а затем старое значение, которое сообщает, что данные были изменены в базе данных на мгновение и снова вернулось к предыдущемузначение.

В чем должна быть проблема и как ее решить?

Вот 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 голосов
/ 21 мая 2018

Я думаю, вы должны сначала получить правильное значение узла, а затем обновить его после увеличения на 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) {

                    }
                });
0 голосов
/ 21 мая 2018

Чтобы решить эту проблему, вам обязательно нужно использовать Транзакции Firebase .

При работе с данными, которые могут быть повреждены одновременными изменениями, такими как добавочные счетчики, вы можете использоватьоперация транзакции.

Для этого, пожалуйста, используйте мой ответ из этой записи , в которой я объяснил, как вы можете увеличить значение в Firebase Realtimeбазы данных и как вы можете прочитать ее обратно.

Вам также необходимо знать, что вы не можете использовать то, что еще не загружено.Другими словами, вы не можете просто использовать объект daysPresent вне метода onDataChange(), потому что он всегда будет null из-за асинхронного поведения этого метода.Это означает, что к тому времени, когда вы пытаетесь использовать этот результат вне этого метода, данные еще не закончили загрузку из базы данных, и поэтому они недоступны, и вы всегда получаете zero.

Aбыстрое решение этой проблемы - использовать daysPresent только внутри метода onDataChange(), или, если вы хотите использовать его снаружи, я рекомендую вам погрузиться в асинхронный мир и посмотреть последнюю часть моего ответа из этого post , в котором я объяснил, как это можно сделать с помощью пользовательского обратного вызова.Вы также можете взглянуть на это видео для лучшего понимания.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...