2

Hello I am using Firebase database for my android app.I have my data stored on firebase database and I want to get it whenever the fragment gets created but when I start my app the method(which gets data from firebase database) returns null and whenever I resume the fragment with the android device the recyclerView gets populated with the data from firebase. My question is why the list returns null first time. and How can I get data whenever the fragment gets created

OffersFragment

 @Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    View offersView = inflater.inflate(R.layout.fragment_offers, container, false);

    mOffersRecyclerView = offersView.findViewById(R.id.rv_offers);
    mAddCard = offersView.findViewById(R.id.fab_add_card);

    setUp();

    return offersView;
}

@Override
public void setPresenter(OffersContract.Presenter presenter) {
    mPresenter = presenter;
}

@Override
public void setUp() {
    mOffersList = mPresenter.getOffersList();
    mOffersAdapter = new OffersAdapter(getActivity(), mOffersList);

    mOffersRecyclerView.setAdapter(mOffersAdapter);
    RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(getActivity());
    mOffersRecyclerView.setLayoutManager(layoutManager);
    mOffersRecyclerView.setHasFixedSize(false);

    performActions(mAddCard);
}

OffersPresenter

 @Override
public List<Offers> getOffersList() {

    return databaseHelper.getOffers();
}

DatabaseHelper -> getOffers()

public List<Offers> getOffers() {
    DatabaseReference offerReference = getDatabase().child("offers");

    offerReference.addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            final Iterable<DataSnapshot> children = dataSnapshot.getChildren();

            for (DataSnapshot d : children) {
                offersList.add(d.getValue(Offers.class));
            }
        }

        @Override
        public void onCancelled(DatabaseError databaseError) {

        }
    });
    return offersList;
}
kemblekaran
  • 174
  • 2
  • 14

2 Answers2

1

The firebase callbacks are async so the method getOffers will return null before it gets updated by callback. You have to pass your adapter instance and list instance to firebase callback so that it update from there Try this mechanism: In your activity initialize your list

@Override
public void setUp() {
    mOffersList = new ArrayList<Offers> ();
    mOffersAdapter = new OffersAdapter(getActivity(), mOffersList);

    mOffersRecyclerView.setAdapter(mOffersAdapter);
    RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(getActivity());
    mOffersRecyclerView.setLayoutManager(layoutManager);
    mOffersRecyclerView.setHasFixedSize(false);

    performActions(mAddCard);
}

Update your getter

@Override
public void getOffersList(List<Offers> offers, OffersAdapter adapter) {

    return databaseHelper.getOffers(offers, adapter);
}

Helper will be like this:

public void getOffers(List<Offers> offers,OffersAdapter adapter) {
    if (offers == null) offers = new ArrayList<Offers> ();
    DatabaseReference offerReference = getDatabase().child("offers");

    offerReference.addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            final Iterable<DataSnapshot> children = dataSnapshot.getChildren();

            for (DataSnapshot d : children) {
                offers.add(d.getValue(Offers.class));
            }
            adapter.notifyDataSetChanged();
        }

        @Override
        public void onCancelled(DatabaseError databaseError) {

        }
    });
}

Keep in mind you are using value event which will gets called if any data changes and as a result data will be added multiple times. Use single value event or Child event listener to solve the issue if you have any.

Umar Hussain
  • 3,461
  • 1
  • 16
  • 38
  • Okay @UmarHussain but what I did is that instead of passing adapter and list to getOfferts() I passed the View from the presenter class to the DatabaseHelper -> getOffers and in there I called setUp() of view and I am calling getOffersList in onCreate of fragment.Is it a good solution or I should use the above?. – kemblekaran Mar 29 '18 at 07:54
  • that will also work, but in the end you have to pass the adapter instance to the firebase callback to update the data. – Umar Hussain Mar 29 '18 at 07:57
  • I don't think so because Firebase provide realtime database capability so the data will be updated as soon as new data gets added in a list adapter – kemblekaran Mar 29 '18 at 08:08
1

It returns null because you are placing your return offersList; at the end of public List<Offers> getOffers() Remove the return statement and make getOffers() void and add logic to Get/Update your data and/or commit() your Fragment inside of onDataChange(DataSnapshot dataSnapshot), so it will return your list when the data is fetched the first time.

What I usually do is to commit the fragment or set its arguments inside of onDataChange(DataSnapshot dataSnapshot)

Guanaco Devs
  • 1,822
  • 2
  • 21
  • 38