2015-05-04 168 views
1

很難解釋的種類。基本上,我有一個名爲數據的列表,我需要添加到該列表。這是我用來做到這一點的代碼...更新嵌套方法中的變量不會全局更新

public static List<WorldBrowseData> getData() { 

    data = new ArrayList<>(); 

    ref.addListenerForSingleValueEvent(new ValueEventListener() { 

     @Override 
     public void onDataChange(DataSnapshot dataSnapshot) { 

      for(DataSnapshot children : dataSnapshot.getChildren()) { 

       WorldBrowseData current = new WorldBrowseData(); 
       Log.v("CHILDREN",children.toString()); 
       current.image = children.child("image_url").getValue().toString(); 
       //Log.v("IMAGE",current.image); 
       data.add(current); 
       Log.v("DATA IN METHOD",data.toString()); 

      } 

     } 

     @Override 
     public void onCancelled(FirebaseError firebaseError) { 

     } 
    }); 

    Log.v("DATA IS",data.toString()); 
    return data; 

} 

當我記錄「數據在方法」,它返回更新,正確的列表。但是當我登錄(並返回)「數據是」時,它只是一個空列表。

另外,它在記錄「DATA IN METHOD」之前記錄「DATA IS」,所以基本上它被調用,返回數據,然後然後更新數據,當我需要更新然後返回時。

我在做什麼錯?

+0

不同的Firebase客戶端平臺,同樣的問題:http://stackoverflow.com/questions/27049342/asynchronous-access-to-an-array-in-firebase/27050749#27050749 –

回答

0

我不知道addListenerForSingleValueEvent,但通常一個偵聽器不一定被調用,只要它被設置,它並不是爲此設計的。它通常被稱爲一個事件。所以你已經定義了你的監聽器,然後記錄了「DATA IS」。您的活動稍後觸發,然後您的數據會更新。

0

直到發生事件(單值事件)時,ValueEventListener中的代碼塊纔會運行。這就是爲什麼你看到你所看到的行爲。通過調用ref.addListenerForSingleValueEvent發生的所有事情都告訴系統在事件上調用該方法。

2

onDataChange方法是異步執行的。在你的情況下,執行的順序是這樣的:

1) data = new ArrayList<>(); 
2) ref.addListenerForSingleValueEvent(... 
3) Log.v("DATA IS",data.toString()); (data is not modified yet) 
4) Log.v("DATA IN METHOD",data.toString());(when the event is called) 

你需要爲了有數據陣列的最後一個版本執行onDataChange方法裏面的代碼。

你可以把它填充後,爲了得到「數據」修改當前的方法:

你需要創建一個監聽器:

public interface OnDataLoadedListener{ 
    public void onFinishLoading(List<WorldBrowseData> data); 
    public void onCancelled(FirebaseError firebaseError); 
} 

然後,你的方法是:

public static void getData(final OnDataLoadedListener listener) { 

    ref.addListenerForSingleValueEvent(new ValueEventListener() { 

     @Override 
     public void onDataChange(DataSnapshot dataSnapshot) { 
      data = new ArrayList<>(); 
      for(DataSnapshot children : dataSnapshot.getChildren()) { 

       WorldBrowseData current = new WorldBrowseData(); 
       Log.v("CHILDREN",children.toString()); 
       current.image = children.child("image_url").getValue().toString(); 
       //Log.v("IMAGE",current.image); 
       data.add(current); 
       Log.v("DATA IN METHOD",data.toString()); 

      } 

      if(listener != null) listener.onFinishLoading(data); 
     } 

     @Override 
     public void onCancelled(FirebaseError firebaseError) { 
      if(listener != null) listener.onCancelled(firebaseError); 
     } 
    });  

} 

你需要調用的方法:

getData(new OnDataLoadedListener(){ 
    public void onFinishLoading(List<WorldBrowseData) data){ 
    //data is populated 
    } 

    public void onCancelled(FirebaseError firebaseError){ 
    //manage the error 
    } 
}); 
+0

你是什麼意思「執行你的代碼裏面onDataChange「? – user3642742

+0

如果你想在執行onDataChange之後用「data」執行任何操作,你需要將該代碼放在該方法中,而不是在調用ref.addListenerForSingleValueEvent(..)之後,而不是像當前那樣。 – mmark

+0

是否有返回值來自getData方法的更新數據? – user3642742