【问题标题】:How deal with Firebase offline mode and data push?Firebase离线模式和数据推送如何处理?
【发布时间】:2016-02-14 10:04:46
【问题描述】:

使用 Firebase 时,建议使用 push() 命令管理数据列表。真的很好,它为列表中推送的数据提供了一个唯一且有序的 id。

但是,当 Firebase 下线(goOffline 或 NetworkOffline)时,如果应用尝试将数据推送到列表中,则不会触发完成侦听器,直到应用重新上线:所以直到行没有唯一 id又开始了。

1/ 这是预期/正常的行为吗?

2/ 我在文档中没有看到(据我记忆),push 命令在离线状态下的工作方式不同(或仅在在线模式下)。我是否在某处漏掉了一行?

3/ 我的用例处理拥有关系的数据。这意味着我想在列表中创建一个对象(一种主对象),然后重用这个主对象 ID(由完成侦听器提供)来建立主对象和所有其他相关对象之间的关系。我该如何处理这种离线状态?

代码示例:

    findViewById(R.id.button3).setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            new Firebase(getString(R.string.firebase_url)).child("stack").push().setValue(counter++, new Firebase.CompletionListener() {
                @Override
                public void onComplete(FirebaseError firebaseError, Firebase firebase) {
                    ((TextView) findViewById(R.id.textView3)).setText(String.valueOf(counter) + " - " + firebase.toString());
                }

            });
        }
    });

编辑

这里有 4 种添加数据的方法:

与监听器一起推送

   findViewById(R.id.button3).setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            new Firebase(getString(R.string.firebase_url)).child("stack").push().setValue(counter++, new Firebase.CompletionListener() {
                @Override
                public void onComplete(FirebaseError firebaseError, Firebase firebase) {
                    ((TextView) findViewById(R.id.textView3)).setText(String.valueOf(counter) + " - " + firebase.toString());
                }

            });
        }
    });

使用监听器设置值

    findViewById(R.id.button4).setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            new Firebase(getString(R.string.firebase_url)).child("stackManual").child(UUID.randomUUID().toString()).setValue(counter++, new Firebase.CompletionListener() {
                @Override
                public void onComplete(FirebaseError firebaseError, Firebase firebase) {
                    ((TextView) findViewById(R.id.textView4)).setText(String.valueOf(counter) + " - " + firebase.toString());
                }

            });
        }
    });

不带监听器的 SetValue

    findViewById(R.id.button5).setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Firebase temp = new Firebase(getString(R.string.firebase_url)).child("stackManual").child(UUID.randomUUID().toString());
            temp.setValue(counter++);


            ((TextView) findViewById(R.id.textView5)).setText(String.valueOf(counter) + " - " + temp.getKey().toString());
        }

    });

无需监听器即可推送

    findViewById(R.id.button6).setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Firebase temp = new Firebase(getString(R.string.firebase_url)).child("stack").push();
            temp.setValue(counter++);

            ((TextView) findViewById(R.id.textView6)).setText(String.valueOf(counter) + " - " + temp.getKey().toString());
        }

    });

似乎只有当数据在服务器上的数据库中而不是在本地数据库中时才会触发侦听器! - 那是对的吗 ? - 有记录吗?

因为知道,现在构建一个直接的异步应用程序更加困难:如果离线,可能无法执行异步作业的封装,不是吗?

【问题讨论】:

    标签: android firebase


    【解决方案1】:

    所以在线路再次打开之前没有唯一的 id

    这最后一个陈述不是正确的。 Firebase 推送 ID 是在客户端生成的,并且在统计上保证是唯一的。

    您可以通过拆分操作轻松检查:

    Firebase ref = new Firebase(getString(R.string.firebase_url));
    Firebase newStackRef = ref.child("stack").push();
    System.out.println("New key/push id: "+newStackRef.key());
    newStackRef.setValue(counter++, new Firebase.CompletionListener() {
    

    即使您没有连接到网络,日志输出也会向您显示新的推送 ID。

    似乎只有当数据在服务器上的数据库中而不是在本地数据库中时才会触发侦听器!对吗?

    只有在服务器上提交数据后才会触发完成侦听器。

    来自guide on saving data

    如果您想知道您的数据何时提交,您可以添加一个完成侦听器。 setValue() 和 updateChildren() 都采用一个可选的完成侦听器,当写入已提交到数据库时调用该侦听器。

    但是,本地和远程编辑都会触发常规事件侦听器(例如使用 addValueEventListener() 创建的侦听器)。这些是您应该用来呈现 UI 等的侦听器。

    【讨论】:

    • 好的,感谢您的澄清。 100% 理解:在本地模式下,setValue() 和 updateChildren() 是否“同步”?
    • 在文档“写入已提交到数据库”中,我理解“数据库”就是您所说的“远程编辑”:这并不容易理解。您可以更新文档以便更好(至少更容易)理解读者。
    • 嘿安东尼,我们不将本地存储称为数据库,而是通常将其称为缓存(或在谈到待处理写入时的队列)。我会看看我们是否可以在文档中更明确地说明这一点。写操作会立即在本地触发相应的事件。乳清可能会在稍后触发其他事件,例如,如果服务器根据安全规则或(在事务的情况下)冲突写入拒绝操作。
    【解决方案2】:

    按照@Andrew-lee 和@Frank-fan-puffelen(感谢双方同意),解决方案似乎是:

    1. 使用 push() 命令创建唯一 ID
    2. 将侦听器(单值)添加到 (1.) 中先前创建的节点的 firebase 引用
    3. 在侦听器中安排您的工作(此处更新 UI,但可能是另一个命令)

      findViewById(R.id.button7).setOnClickListener(new View.OnClickListener() {
          @Override
          public void onClick(View v) {
              Firebase temp = new Firebase(getString(R.string.firebase_url)).child("stack").push();
              temp.addListenerForSingleValueEvent(new ValueEventListener() {
                  @Override
                  public void onDataChange(DataSnapshot dataSnapshot) {
                      ((TextView) findViewById(R.id.textView7)).setText(String.valueOf(counter) + " - " + dataSnapshot.getKey().toString());
                  }
      
                  @Override
                  public void onCancelled(FirebaseError firebaseError) {
      
                  }
              });
              temp.setValue(counter++);
      
      
          }
      
      });
      

    【讨论】:

      猜你喜欢
      • 2019-06-11
      • 1970-01-01
      • 2017-01-12
      • 1970-01-01
      • 2017-01-01
      • 2014-08-14
      • 1970-01-01
      • 2020-03-19
      • 1970-01-01
      相关资源
      最近更新 更多