如何处理Firebase离线模式和数据推送?

时间:2015-11-12 22:06:13

标签: android firebase

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

但是,当Firebase脱机(goOffline或NetworkOffline)时,如果应用尝试在列表中推送数据,则不会触发完成侦听器,直到应用程序重新联机:因此在该行之前没有唯一ID又来了。

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

2 /我没有在文档中看到(据我记得),push命令在脱机状态下的工作方式不同(或仅在onlinemode中)。我在某个地方错过了一条线吗?

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());
                }

            });
        }
    });

带监听器的SetValue

    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());
        }

    });

显示只有当数据在服务器上的数据库中时,才会触发听众,而不是在本地数据库上! - 那是对的吗 ? - 那是文件吗?

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

2 个答案:

答案 0 :(得分:10)

  

所以在该行重新开启之前没有唯一的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等的监听器。

答案 1 :(得分:2)

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

  1. 使用push()命令
  2. 创建唯一ID
  3. 将侦听器(单值)添加到(1。)
  4. 中先前创建的节点的firebase引用中
  5. 在侦听器中安排您的工作(此处更新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++);
    
    
        }
    
    });