Joey LU
Joey LU

Reputation: 77

How to fill the RecyclerView with nested object from firebase

This is the event object that I want to inflate with RecyclerView:

public class Event {
private String mName;
private String mId;
private String mDate;
private String mPlace;
private User mUser;
private Category mCat;
private String mDescription;

public void setmEventCat(Map<String, Category> mEventCat) {
    this.mEventCat = mEventCat;
}

public Map<String, Category> getmEventCat() {

    return mEventCat;
}

private Map<String,Category> mEventCat;

public String getmDescription() {
    return mDescription;
}

public void setDescription(String mDescription) {
    this.mDescription = mDescription;
}

public Category getCat() {
    return mCat;
}

public void setCat(Category mCat) {
    this.mCat = mCat;
}

public String getDate() {
    return mDate;
}

public String getPlace() {
    return mPlace;
}

private ArrayList<User> mList;

public Event() {
}

public String getName() {
    return mName;
}

public void setName(String mName) {
    this.mName = mName;
}

public void setDate(String mDate) {
    this.mDate = mDate;
}

public void setPlace(String mPlace) {
    this.mPlace = mPlace;
}

public String getId() {
    return mId;
}

public void setId(String mId) {
    this.mId = mId;
}

}

The nested Category object:

public class Category implements Serializable{
private String mCatName;
private String mCatID;

public Category() {
}

public Category(String mCatName) {
    this.mCatName = mCatName;

}

public String getCatName() {
    return mCatName;
}

public String getCatID() {
    return mCatID;
}

public void setCatName(String mCatName) {
    this.mCatName = mCatName;
}

public void setCatID(String mCatID) {
    this.mCatID = mCatID;
}

}

How I retrieve the data from firebase:

    mDataBase = FirebaseDatabase.getInstance().getReference("Event");

    mEvents = new ArrayList<Event>();
    mEvent=new Event();
    mRecyclerView = (RecyclerView) rootView.findViewById(R.id.recycler_view);

    mDataBase.addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            if (dataSnapshot != null && dataSnapshot.getValue() != null) {
                try {
                    for (DataSnapshot eventSnapshot : dataSnapshot.getChildren()) {
                        Event event = eventSnapshot.getValue(Event.class);
                        String id = eventSnapshot.getKey();
                        mEvents.add(event);
                        mRecyclerView.scrollToPosition(mEvents.size() - 1);
                        mAdapter.notifyItemInserted(mEvents.size() - 1);
                    }

                }
                catch (Exception ex) {
                    Log.e("ERROR", ex.getMessage());
                }
            }
        }



        @Override
        public void onCancelled(DatabaseError databaseError) {

        }
    });


    mAdapter = new EventAdapter(mContext, mEvents);
    mRecyclerView.setAdapter(mAdapter);
    mRecyclerView.setLayoutManager(new LinearLayoutManager(mContext));

My EventAdapter:

    @Override
public void onBindViewHolder(EventAdapter.ViewHolder holder, int position) {
    mEvent = mEvents.get(position);
    holder.mEventName.setText(mEvent.getName());

    //Every time I tried to add this line to set category name
    //the NullPointerException error occurs
    holder.mEventCategory.setText(mEvent.getCat().getCatName());
    holder.mEventDate.setText(mEvent.getDate());
}

The ViewHolder Class:

    public class ViewHolder extends RecyclerView.ViewHolder {

    private TextView mEventName, mEventDate,mEventCategory;

    public ViewHolder(View itemView) {
        super(itemView);
        mEventName = itemView.findViewById(R.id.eventName_tv);
        mEventDate = itemView.findViewById(R.id.date_tv);
        mEventCategory = itemView.findViewById(R.id.categoryTv);



    }
}


@Override
public EventAdapter.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
    View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.search_event, parent, false);

    return new ViewHolder(view);
}

The problem is the Event is displayed as I expected, but I cannot get the category inside the event and bind it to my widget by simply calling the getCat(). I know this may caused by asynchronous Firebase API. How can I set up the TextView with the nested category object.

This is my FINAL piece of my application, any hints would be a great help. Thanks in advance!

Upvotes: 2

Views: 952

Answers (1)

Joey LU
Joey LU

Reputation: 77

I figure out the question that may be useful for other people. Before adding the event object to the list, I retrieve the nested object by key and assign it to category object. Finally, linking it with event...

 @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            if (dataSnapshot != null && dataSnapshot.getValue() != null) {
                try {
                    for (DataSnapshot eventSnapshot : dataSnapshot.getChildren()) {
                        Event event = eventSnapshot.getValue(Event.class);
                        String id = eventSnapshot.getKey();
                        mCategory = eventSnapshot.child(id).getValue(Category.class);
                        event.setCat(mCategory);
                        mEvents.add(event);
                        mRecyclerView.scrollToPosition(mEvents.size() - 1);
                        mAdapter.notifyItemInserted(mEvents.size() - 1);
                    }

                }
                catch (Exception ex) {
                    Log.e("ERROR", ex.getMessage());
                }
            }
        }

Then binding the desired data with widget by calling the pojo getter method (nothing's changed here).

    @Override
public void onBindViewHolder(EventAdapter.ViewHolder holder, int position) {
    mEvent = mEvents.get(position);
    holder.mEventName.setText(mEvent.getName());
    holder.mEventCategory.setText(mEvent.getCat().getCatName());
    holder.mEventDate.setText(mEvent.getDate());
}

Upvotes: 1

Related Questions