java - Firebase Android 以最佳方式读取数据

标签 java android firebase firebase-realtime-database

该方法执行过程中,需要从同一个分支获取2组数据。然后调整值并写回。如何正确组织这个方法?我通过嵌套听众来做到这一点。有没有更正确的做法呢?当 Firebase 写入命令成功时,如何让此方法返回结果(例如 boolean 值)?

方法代码:

public static void UpdateBalancesInFB (final long DateMove, final double DeltaValue, DatabaseReference FBRef){
    //TODO: как получить успешное выполнение метода?!
    final DatabaseReference mDBref = FBRef.child(MyTypesAndUtils.sFB_Balances);
    final boolean result = false;

    /*получаем с Firebase выгрузку последней записи и данных следующих за Date_min */
    final Query mQuery = mDBref.orderByKey();
    mQuery.limitToLast(1).addListenerForSingleValueEvent(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            final long[] Date_last = {DateMove};
            final double[] Value_last = {DeltaValue};

            for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
                Date_last[0] = Long.valueOf(snapshot.getKey());
                Value_last[0] = snapshot.getValue(Double.class);
            }
            mQuery.startAt(String.valueOf(DateMove)).addListenerForSingleValueEvent(new ValueEventListener() {
                @Override
                public void onDataChange(DataSnapshot dataSnapshot) {
                    boolean mark = false;
                    Map<String, Object> mQueryBalances = new HashMap<>();
                    for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
                        mQueryBalances.put(snapshot.getKey(), snapshot.getValue());
                        mark = true;
                    }
                    /*корректируем значения остатков после даты движения*/
                    for (HashMap.Entry<String, Object> entry : mQueryBalances.entrySet()) {
                        Date_last[0] = Long.valueOf(entry.getKey());
                        Value_last[0] = Double.valueOf(entry.getValue().toString()) + DeltaValue;
                        mQueryBalances.put(entry.getKey(), Value_last[0]);
                    }

                    /*дополняем коллекцию недостающими элементами до даты движения и 1 элемент после нее*/
                    //это возможно только если mQueryBalances пустой
                    Calendar calendar = Calendar.getInstance();
                    calendar.setTimeInMillis(Date_last[0]);         //последняя запись остатков
                    calendar.set(Calendar.DAY_OF_MONTH, 1);         //переводим на 1й день месяца (на всякий случай)

                    while (!mark) {                                 // это возможно только если mQueryBalances пустой
                        calendar.add(Calendar.MONTH, 1);
                        Date_last[0] = calendar.getTimeInMillis();
                        if (Date_last[0] <= DateMove)
                            mQueryBalances.put(String.valueOf(Date_last[0]), Value_last[0]);
                        else{
                            mQueryBalances.put(String.valueOf(Date_last[0]), Value_last[0]+DeltaValue);
                            mark = true;
                        }
                    }

                    /*Записываем в Firebase*/
                    mDBref.updateChildren(mQueryBalances, new DatabaseReference.CompletionListener() {
                        @Override
                        public void onComplete(DatabaseError databaseError, DatabaseReference databaseReference) {
                            //result = true;
                        }
                    });
                }

该方法的调用代码也是在监听器内部执行:

myRef.child(MyTypesAndUtils.sFB_Movements).child(mMove_output.getKeyFB()).setValue(mMove_output).addOnSuccessListener(this, new OnSuccessListener<Void>() {
        @Override
        public void onSuccess(Void aVoid) {
            long Date2, Date1;
            double Value2, Value1;

            Date2 = mMove_output.getDateInMilisec();
            Value2 = mMove_output.getValue()*mMove_output.getKind();
            if (mMove_input != null) {
                Date1 = mMove_input.getDateInMilisec();
                Value1 = mMove_input.getValue()*mMove_input.getKind();
                if (Date2==Date1)
                    MyTypesAndUtils.UpdateBalancesInFB(Date2, (Value2-Value1), myRef);
                else {
                    MyTypesAndUtils.UpdateBalancesInFB(Date1, (-Value1), myRef);
                    MyTypesAndUtils.UpdateBalancesInFB(Date2, Value2, myRef);
                }
            }
            else    MyTypesAndUtils.UpdateBalancesInFB(Date2, (Value2), myRef);

            Toast.makeText(getApplicationContext(), "Сохранение произошло", Toast.LENGTH_SHORT).show(); //TODO: переписать в string
            finish();
        }
    });

最佳答案

只要按照 life-cycle of your activity 删除嵌套监听器就没有问题。 。所以你的代码看起来是正确的。有一种方法可以使用自定义回调实现相同的效果,但不需要使用它们,而是使用这个简单的嵌套监听器示例。

关于java - Firebase Android 以最佳方式读取数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50667061/

相关文章:

java - 确定名词/动词的复数

java - 多项式 GUI 不起作用

java - 参数值 [vbs@gmail.com] 与预期类型 [java.lang.Long (n/a)] 不匹配;嵌套异常是 java.lang.IllegalArgumentException :

android - 如何从Facebook相册中获取图像

android - 如何在没有 OutOfMemoryError 的情况下填充图像 ListView

c# - Xamarin Android,从内部存储/下载中读取一个简单的文本文件

Java:showInputDialog 中的自定义按钮

javascript - 消息的时间戳

android - 获取 cloud_firestore : 0. 9.0 依赖项破坏了 flutter 应用程序

Android 身份验证错误 : "GetToken failed with status code: INVALID_AUDIENCE"