在Android中如何将Firebase子节点从一个节点移动到另一个节点?

11

我正在处理一个项目,用户可以请求我们的代客泊车服务,而代客泊车者则接受请求。

我使用 Firebase 作为后端,当用户发出请求时,用户 uid 将保存在“request”子节点上。

当代客泊车者接受请求时,用户 uid 应从“request”节点移动到“on progress”节点。

如何实现这一点?

4个回答

10

我建议使用这个:

public void moveFirebaseRecord(Firebase fromPath, final Firebase toPath)
{
    fromPath.addListenerForSingleValueEvent(new ValueEventListener()
    {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot)
        {
            toPath.setValue(dataSnapshot.getValue(), new Firebase.CompletionListener()
            {
                @Override
                public void onComplete(FirebaseError firebaseError, Firebase firebase)
                {
                    if (firebaseError != null)
                    {
                        System.out.println("Copy failed");
                    }
                    else
                    {
                        System.out.println("Success");
                    }
                }
            });
        }

        @Override
        public void onCancelled(FirebaseError firebaseError)
        {
            System.out.println("Copy failed");
        }
    });
}
这来自于这个来源:https://gist.github.com/katowulf/6099042。我在我的JavaEE代码和Android应用程序中多次使用它。您需要传递fromPath和toPath参数。这是一次复制而非移动操作,因此原始文件仍将保留在其原始位置。如果您想要删除,请在System.out.println("Success");后对fromPath进行设置。

它可以正常工作,但它使用Firebase URL作为路径(ref)并移动所有子级。我只想移动选择的其中一个子级。如何移动仅一个子级?TIA - Shakeel Dhada
如果您有孩子的ID,则可以直接从一个ID移动到另一个ID。 - Ali Haidar
它想要:将myfirebase.firebase.com/initialPlace/ID转换为myfirebase.firebase.com/finalPlace/ID。您可以将任何字符串作为变量传递给Firebase构造函数。 - Ali Haidar

9
截至编译firebase-database:11.0.1版本,这是一个带有新类引用的相同函数。 (https://firebase.google.com/support/guides/firebase-android 2017年7月5日)
private void moveGameRoom(final DatabaseReference fromPath, final DatabaseReference toPath) {
        fromPath.addListenerForSingleValueEvent(new ValueEventListener() {
            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {
                toPath.setValue(dataSnapshot.getValue(), new DatabaseReference.CompletionListener() {
                    @Override
                    public void onComplete(DatabaseError firebaseError, DatabaseReference firebase) {
                        if (firebaseError != null) {
                            System.out.println("Copy failed");
                        } else {
                            System.out.println("Success");

                        }
                    }
                });

            }

            @Override
            public void onCancelled(DatabaseError databaseError) {

            }
        });
    }

3
如果您想执行一个同时也删除原始数据的操作,您可以使用以下代码片段:
// In this piece of code, "fromPath" and "toPath" parameters act like directories.
private void removeFromFirebase(final DatabaseReference fromPath, final DatabaseReference toPath, final String key) {
    fromPath.child(key).addListenerForSingleValueEvent(new ValueEventListener() {
        // Now "DataSnapshot" holds the key and the value at the "fromPath".
        // Let's move it to the "toPath". This operation duplicates the
        // key/value pair at the "fromPath" to the "toPath".
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            toPath.child(dataSnapshot.getKey())
                    .setValue(dataSnapshot.getValue(), new DatabaseReference.CompletionListener() {
                        @Override
                        public void onComplete(DatabaseError databaseError, DatabaseReference databaseReference) {
                            if (databaseError == null) {
                                Log.i(TAG, "onComplete: success");
                                // In order to complete the move, we are going to erase
                                // the original copy by assigning null as its value.
                                fromPath.child(key).setValue(null);
                            }
                            else {
                                Log.e(TAG, "onComplete: failure:" + databaseError.getMessage() + ": "
                                        + databaseError.getDetails());
                            }
                        }
                    });
        }

        @Override
        public void onCancelled(DatabaseError databaseError) {
            Log.e(TAG, "onCancelled: " + databaseError.getMessage() + ": "
                    + databaseError.getDetails());
        }
    });
}

键的值是多少? - LizG
在JavaScript对象中,“键”将是与非空值相关联的任何属性名称。 “fromPath”将是导致该键的对象分支,而“toPath”将是将导致该键的对象分支。例如: { user1: { name: 'Jack', address: { line1: 'some st', } } }如果您想要移动的是地址,则键将是“address”,fromPath将是“/user1/”,而toPath将是“/junkAddress/user1/”。键也可以是推送键。 - felixy
当我删除内容时,如何获取“key”的值。基本上,当我调用removeFromFirebase(fromPath, toPath, key)方法时,如何获取“key”的值? - LizG
你只需要执行 toPath.child(key).addListenerForSingleValueEvent(/***/); 就可以从新路径中检索到相同的值。 - felixy
在这种情况下,如果有并发的移动操作,同一段代码可能会被多次运行。所以你是对的。使用事务也会简化代码。你只需要从回调函数中返回 null。问题是,在这种情况下,内部的设置操作不能失败,否则你需要同步运行它。因为如果失败了,你就会失去原始值。 - felixy

2

您可以在要复制的子项上侦听值事件,然后使用 #onDataChange 获取新子项的引用,并将 dataSnapshot 的值设置为此子项,如下面的示例代码所示。

FirebaseDatabase.getInstance().getReference("childYouWantToCopy")
                    .addListenerForSingleValueEvent(new ValueEventListener() {
                @Override
                public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
                    FirebaseDatabase.getInstance().getReference("ChildCopyTo").setValue(dataSnapshot.getValue());
                }

                @Override
                public void onCancelled(@NonNull DatabaseError databaseError) {

                }
            });

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接