Android 上的 Firebase - 如何在我需要时触发数据检索事件处理程序?

Firebase on Android - how to make event handler for data retrieval fire when I need it to?

我是 Firebase 的新手,需要一些查询方面的帮助以从 table 检索数据。我目前能够从 firebase 访问和检索我需要的数据,但是,时间是我遇到的问题。

根据我所见,firebase 数据库要求我将事件侦听器添加到 Query 或 DatabaseReference 对象。我试图在调用显示问题内容的方法之前下载名为 "questions" 的节点的内容,但是,我无法控制下载数据的事件的触发时间,结果我display 方法总是在 firebase 事件触发之前被调用。

我怎样才能在需要时执行查询,并确保它会在我的代码的特定部分执行之前完成?我习惯于传统的 RDB,您可以在其中执行查询并获取结果,然后继续执行您的逻辑。需要将事件处理程序与 firebase 一起使用是我遇到的困难。我什至尝试将 firebase 引用对象和事件处理程序的定义移到 onCreate() 中,并将调用我的显示方法的代码移到 onStart() 中,但没有成功——同样的问题。我要获取的数据是不会变的,所以我只需要在开始的时候下载一次就可以使用显示方法了。

这是我的 "questions" 节点的图像,它是根的子节点。 我的 firebase DB

上子 "questions" 节点的图像

这是我的代码:

    @Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    // Get Firebase DB reference
    firebase = FirebaseDatabase.getInstance();
    fdbRef = firebase.getReference("questions");

    // [START Question_event_listener]
    fdbRef.addListenerForSingleValueEvent(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            // Get Questions object and use the values to update the UI
            objQuestions = dataSnapshot.getValue();
            Log.w("Firebase:", "In Firebase ValueEventListener");
        }

        @Override
        public void onCancelled(DatabaseError databaseError) {
            // Getting Questions failed, log a message
            Log.w("Firebase Error:", "onCancelled:", databaseError.toException());
            Toast.makeText(ReviewActivity.this, "Failed to load question!", Toast.LENGTH_SHORT).show();
        }
    });
    //. . . remaining onCreate logic removed for simplicity
} //end of onCreate

@Override
public void onStart() {
    super.onStart();

    // I moved this logic from onCreate to onStart but did not help...
    // Firebase retrieve must execute before I call any of these
    if (list_type == MainActivity.LIST_UNREVIEWED_DOCS)
        displayNewReviewForm();
    else if (list_type == MainActivity.LIST_REVIEWS)
        displayCompletedReview();
    else // (list_type == MainActivity.LIST_DRAFTS)
        displayDraftReview();
}

如果我无法解决此问题,其他替代方案可能是将此检索逻辑移动到我序列中的先前 Activity 并将检索到的数据作为额外传递给此 activity - 但是不得不做这样的事情似乎真的很愚蠢。我认为我应该能够在需要时从数据库中获取数据……而不是在感觉要给我的时候。

非常感谢帮助我解决这个问题的任何帮助。

你的代码只是在第一次下载包含所有数据的快照数据,而使用Firebase,你无法及时下载数据,你只能通过不同的引用来完成。

我建议你做的是,分别拥有 q01、q02 的 DatabaseReference,然后在需要时调用数据。

如果您的密钥 "q01"、"q02" 是静态的,他们正在查看场景。我建议你有他们的 DatabaseReferences:

question_one = firebase.getReference("q01");
question_two = firebase.getReference("q02");
question_three = firebase.getReference("q03");


//Once you have the reference, you can call their ValueListeners respectively
question_one.addListenerForSingleValueEvent(new ValueEventListener() {
    @Override
    public void onDataChange(DataSnapshot dataSnapshot) {
        // Get Questions object and use the values to update the UI
        objQuestions = dataSnapshot.getValue();
        Log.w("Firebase:", "In Firebase ValueEventListener");
    }

    @Override
    public void onCancelled(DatabaseError databaseError) {
        // Getting Questions failed, log a message
        Log.w("Firebase Error:", "onCancelled:", databaseError.toException());
        Toast.makeText(ReviewActivity.this, "Failed to load question!", Toast.LENGTH_SHORT).show();
    }
});

在进一步研究之后,我想出了 2 种可能的解决方案来解决我遇到的问题。

  1. 我在最初的问题 post 中已经提到了第一个,但我认为它并不理想。它基本上涉及将 firebase 检索逻辑重新定位到先前的 Android Activity 并将检索到的数据传递给 Activity 我需要它作为额外的。在我的例子中,数据是一个 HashMap,所以我需要使用方法的序列化版本将序列化的内容传递给所需的 Activity.
  2. 最好的解决方案,简单得多。我基本上重新定位了我在 onStart() 函数(它正在调用我的自定义显示方法)中的逻辑,并将其移动到 Firebase 事件侦听器的 onDataChange() 方法中,就在调用 dataSnapshot.getValue() 之后。这确保我在调用显示方法之前获取数据。这似乎现在运作良好。