2016-11-06 111 views
0

我把下面的方法放在onCreate()裏面,當應用程序啓動時它會觸發這個方法。但是,當我嘗試在ValueEventListener()之外獲得mName時,它將返回null並且應用程序崩潰。Firebase檢索數據空外部方法

任何人都知道爲什麼會發生這個問題?

ValueEventListener postListener = new ValueEventListener() { 
     @Override 
     public void onDataChange(DataSnapshot dataSnapshot) { 
      UserDetails info = dataSnapshot.getValue(UserDetails.class); 
      Log.d(TAG, String.valueOf(dataSnapshot)); 

      mName = info.getName(); 
      **Log.d(TAG, mName); // HERE GET THE NAME** 

     } 

     @Override 
     public void onCancelled(DatabaseError databaseError) { 
      Log.w(TAG, "getUser:onCancelled", databaseError.toException()); 
     } 
    }; 
    mDatabase.child("Admin") 
      .child("Info") 
      .child(uid) 
      .addValueEventListener(postListener); 

    **Log.d(TAG, mName); // HERE GET NULL** 

回答

1

那你做對的時候是因爲火力地堡仍然沒有檢索數據尚未:

Log.d(TAG, mName); 

mName因爲火力地堡得到的數據之前,該行的執行目前爲空。

要解決這個問題,你必須Log.d(TAG, mName)裏面onDataChange方法。否則,由於您尚未設置價值,因此它將爲null(因爲Firebase尚未獲得該值)。

1

正如其他人所說:來自Firebase數據庫的所有數據都是異步讀取的。這是最簡單的通過增加更多的日誌報表,以你的代碼,看看這個:

Log.d(TAG, "Before attaching listener"); 
mDatabase.child("Admin") 
     .child("Info") 
     .child(uid) 
     .addValueEventListener(new ValueEventListener() { 
    @Override 
    public void onDataChange(DataSnapshot dataSnapshot) { 
     Log.d(TAG, "In listener's onDataChange"); 
    } 

    @Override 
    public void onCancelled(DatabaseError databaseError) { 
     Log.w(TAG, "getUser:onCancelled", databaseError.toException()); 
    } 
}); 
Log.d(TAG, "After attaching listener"); 

不像你可以期待什麼,這個輸出是:

之前安裝監聽器

連接監聽器後

內聽者的onDataChange

處理異步行爲的方法是重構您的問題。

現在您的代碼被寫入:首先我們加載數據,然後我們記錄它。

如果你重新定義這個問題:「當數據被加載,我們記錄它」,你會得到這樣的代碼:

mDatabase.child("Admin") 
     .child("Info") 
     .child(uid) 
     .addValueEventListener(new ValueEventListener() { 
    @Override 
    public void onDataChange(DataSnapshot dataSnapshot) { 
     UserDetails info = dataSnapshot.getValue(UserDetails.class); 
     Log.d(TAG, String.valueOf(dataSnapshot)); 

     mName = info.getName(); 
     Log.d(TAG, mName); 

    } 

    @Override 
    public void onCancelled(DatabaseError databaseError) { 
     Log.w(TAG, "getUser:onCancelled", databaseError.toException()); 
    } 
}); 

因此,所有的代碼,需要的數據,需要將內部的onDataChange() 。或者,您可以製作自己的自定義回調方法,並調用onDataChange()。但是邏輯總是相同的:需要數據的代碼在數據可用時從onDataChange()觸發

+0

很好的解釋,非常感謝。但是,這出現了另一個問題,我該如何將數據傳遞給現場的另一項活動。我試圖在onDataChange方法中使用sqlite存儲數據。但要檢索它,我必須關閉並重新打開該應用程序。 – user3606920