Java Firebase使用更新方法不断更新,并且不停止?

Java Firebase使用更新方法不断更新,并且不停止?,java,android,firebase,google-cloud-firestore,Java,Android,Firebase,Google Cloud Firestore,我创建了一个日期跟踪应用程序,它基本上允许用户有30天的固定假期津贴,因为他们预订/选择的每一天都将从总津贴中扣除。问题是,每次我尝试用新值更新firebase数据库时,它都会无限循环,并且不会停止。如何更新数据库一次 我的数据库代码: public void updateDaysCalc() { fAuth = FirebaseAuth.getInstance(); fStore = FirebaseFirestore.getInstance();

我创建了一个日期跟踪应用程序,它基本上允许用户有30天的固定假期津贴,因为他们预订/选择的每一天都将从总津贴中扣除。问题是,每次我尝试用新值更新firebase数据库时,它都会无限循环,并且不会停止。如何更新数据库一次

我的数据库代码:

 public void updateDaysCalc() {
        fAuth = FirebaseAuth.getInstance();
        fStore = FirebaseFirestore.getInstance();
        //get current user information
        final String userId = fAuth.getCurrentUser().getUid();

        final DocumentReference documentReference = fStore.collection("users").document(userId);
        documentReference.addSnapshotListener(this, new EventListener<DocumentSnapshot>() {
            @Override
            public void onEvent(@Nullable DocumentSnapshot documentSnapshot, @Nullable FirebaseFirestoreException e) {
                Long currentAllowance = documentSnapshot.getLong("annualHoliday");

                if (currentAllowance > 0) {

                    long minusDays = countDays();
                    long newHolidayAllowance = currentAllowance - minusDays;

                    documentReference.update("annualHoliday", newHolidayAllowance).addOnSuccessListener(new OnSuccessListener<Void>() {
                        @Override
                        public void onSuccess(Void aVoid) {

                            Log.d(TAG, "onSuccess: Fields have been updated successfully.");

                        }
                    }).addOnFailureListener(new OnFailureListener() {
                        @Override
                        public void onFailure(@NonNull Exception e) {
                            Log.d(TAG, "onFailure: Field have failed to update.");
                        }
                    });

                    return;

                } else {
                    System.out.println("Unavailable");
                }

            }
        });
    }

调用
documentReference.addSnapshotListener
时,您将向该文档添加一个永久侦听器。此侦听器会立即使用文档的当前数据调用,然后在数据发生更改时也会调用它

现在,在侦听器的
onEvent
中,调用
documentReference.update
。这将更改数据库中文档的数据,因此(如上所述)再次触发侦听器。因此,您的
onEvent
会再次被调用,这会再次更新数据,并导致它一次又一次地触发

如果您想更新数据而不引起这样的循环,您有几个选项:

  • 使用而不是
    addSnapshotListener
    get
    方法(顾名思义)只获取文档的值一次,并且不会被进一步的更改触发。这是最简单的修复,因为您不必更改大部分代码

  • 使用以原子方式读取和更新文档。当文档中的新数据依赖于现有数据时,这是必要的,就像这里的情况一样。您应该使用事务的原因是为了防止其他用户在读取数据值和写回更新之间更改数据

  • 使用调用以原子方式递增或递减服务器上的字段值。这是一个比以前的事务更简单的调用,但我无法立即看出这是否适用于您的代码,因为现在在
    onEvent
    调用中发生了很多事情


  • 你能分享你的firebase firestore数据结构吗?它是如何储存的?显示节点的SS或JSON会很有帮助。
     public int countDays () {
    
            CalendarInfo ci = new CalendarInfo();
    
            final String startYearData = ci.getStartDateYear();
            final String startMonthData = ci.getStartDateMonth();
            final String startDayData = ci.getStartDateDay();
    
            int setStartDayDate = Integer.parseInt(startDayData);
            int setStartMonthDate = Integer.parseInt(startMonthData);
            int setYearDate = Integer.parseInt(startYearData);
    
            //beginning
            Calendar calendar = Calendar.getInstance();
            calendar.set(Calendar.DAY_OF_MONTH, setStartDayDate);
            calendar.set(Calendar.MONTH, setStartMonthDate);
            calendar.set(Calendar.YEAR, setYearDate);
            Date startDates = calendar.getTime();
    
            final String endMonthData = ci.getEndDateMonth();
            final String endDayData = ci.getEndDateDay();
    
            int setEndDayDate = Integer.parseInt(endDayData);
            int setEndMonthDate = Integer.parseInt(endMonthData);
    
            //ending
            calendar.set(Calendar.DAY_OF_MONTH, setEndDayDate);
            calendar.set(Calendar.MONTH,setEndMonthDate);
            Date endDates = calendar.getTime();
            //
            calendar.setTime(startDates);
            Date dateIterate = null;
    
            //counters
            int dayCounter = 0;
    
            while ((dateIterate = calendar.getTime()).before(endDates) || dateIterate.equals(endDates)) {
                int day = calendar.get(Calendar.DAY_OF_WEEK);
                if (day != Calendar.SATURDAY && day != Calendar.SUNDAY) {
                    dayCounter++;
                    //System.out.println(dateIterate);
                }
                calendar.add(Calendar.DAY_OF_MONTH, 1);
            }
    
            return dayCounter;
    
        }