I'm trying to get some database' child from Firebase database and put its values into ArrayList<MyClass>
for using in Recyclerview.Adapter
, but after the completion of data appending process in onDataChange
method my list equals null.
I understand that it happens because of asynchronous behavior of onDataChange. Thanks to this answer How to return dataSnapshot value as a result of a method? I've created my FirebaseCallback interface and yes I do get my arrayList.
But I get it only inside its onCallback method.
However, I need to pass the arrayList outside of that method to RecyclerView.Adapter.
Do I have to rebuild my RecylerView.Adapter
and create that one inside the onCallback method?
Please, can anybody explain me how to figure out my problem?
Thanks a lot!
About my code:
I have a SentintelActivity that has to show the list of Sentinel using the RecyclerView. Sentinel is a class of entity that i fetch from FirebaseDatabase. Another class SentinelStorage is a singleton with main field List and a method readSentinelsListFromDB which has to return my list of Sentinels. At the moment that list equals null.
In addition to code, I've attached a schema for more clearly understanding.
My callback interface:
import java.util.List;
public interface FirebaseCallback {
void onCallback (List<Sentinel> list);
}
My singleton class:
public class SentinelStorage { // Singleton class
public static SentinelStorage sentinelStorage;
private List<Sentinel> sentinelsList;
...
public List<Sentinel> readSentinelsListFromDB(DatabaseReference dbRef, final FirebaseCallback firebaseCallback){
final Sentinel sentinel = new Sentinel();
ValueEventListener valueEventListener = new ValueEventListener() {
@Override
public void onDataChange(DataSnapshot dataSnapshot) {
GenericTypeIndicator<Map<String, Object>> t = new GenericTypeIndicator<Map<String, Object>>(){};
Map<String, Object> sentinelsMap = dataSnapshot.getValue(t);
for (Map.Entry<String,Object> entry : sentinelsMap.entrySet()){
// convert every node of Map to Sentinel instance
sentinelsList.add(sentinel.mapToSentinel((Map)entry.getValue()));
}
firebaseCallback.onCallback(sentinelsList);
}
@Override
public void onCancelled(DatabaseError databaseError) {
Log.d(TAG,databaseError.getMessage());
}
};
dbRef.addListenerForSingleValueEvent(valueEventListener);
return sentinelsList; // here sentinelsList still is not empty
}
...
}
SentinelActivity class:
public class ActSentinel extends BaseActivity implements FirebaseCallback{
private static final String TAG = "# ActSentinel";
RecyclerView mRecyclerView;
SentinelViewAdapter adapter;
private final String DBSentintelName = "sentinel";
Sentinel sentinel = new Sentinel();
FirebaseDatabase mFirebaseDatabase = FirebaseDatabase.getInstance();
DatabaseReference dbRef = mFirebaseDatabase.getReference(DBSentintelName);
List<Sentinel> list = new ArrayList<>();
SentinelStorage sentinelStorage;
@Override
public void onCallback(List<Sentinel> lst) {
list.addAll(lst);
adapter.notifyDataSetChanged();
Log.d(TAG, "INSIDE onCallback list empty :: "+list.isEmpty());
}
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.sentinel_view);
mRecyclerView = (RecyclerView)findViewById(R.id.recyclerView);
mRecyclerView.setLayoutManager(new LinearLayoutManager(this));
adapter = new SentinelViewAdapter(list);
sentinelStorage = SentinelStorage.get();
//sentinelStorage.loadSentinelsListFromDB(dbRef);// testing with notnull list
sentinelStorage.readSentinelsListFromDB(dbRef, this);
mRecyclerView.setAdapter(adapter);
Log.d(TAG, "!!!! list empty :: "+list.isEmpty());
}
public class SentinelViewHolder extends RecyclerView.ViewHolder{
Sentinel sentinel;
TextView tvLogin;
TextView tvPassword;
TextView tvName;
TextView tvSurname;
SentinelViewHolder(View view){
super(view);
tvLogin = (TextView) view.findViewById(R.id.login_value);
tvPassword = (TextView) view.findViewById(R.id.password_value);
tvName = (TextView) view.findViewById(R.id.name);
tvSurname = (TextView) view.findViewById(R.id.surname);
}
public void bind (Sentinel sentinel){
this.sentinel = sentinel;
tvLogin.setText(sentinel.login);
tvPassword.setText(sentinel.password);
tvName.setText(sentinel.name);
tvSurname.setText(sentinel.surname);
}
}
public class SentinelViewAdapter extends RecyclerView.Adapter<SentinelViewHolder>{
List<Sentinel> mSentinels;
public SentinelViewAdapter(List<Sentinel> guards){
mSentinels = guards;
}
public SentinelViewHolder onCreateViewHolder(ViewGroup container, int viewType){
View view = LayoutInflater.from(container.getContext())
.inflate(R.layout.item_of_sentinel_table, container,false);
SentinelViewHolder vh = new SentinelViewHolder(view);
return vh;
}
public void onBindViewHolder(SentinelViewHolder sentinelVH, int position){
Sentinel sentinel = mSentinels.get(position);
sentinelVH.bind(sentinel);
}
public int getItemCount(){
return mSentinels.size();
}
}
}