Search code examples
androidfirebaseandroid-fragmentsfirebase-realtime-databaseandroid-mvp

How to retrieve data from firebase database without listening for events


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;
}

Solution

  • 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.