2

I have this scenario where in my app i am trying to query the child nodes and pass it on the list to recyclerview adapter and here comes the problem when i am scrolling up the recycler view items and if some one has inserted a post, my recyclerview is again coming to first post item and also i am using the viewpager with three fragments and whatever fragment i am on I am rolling back to the first fragment if some one has inserted the post how to solve this. I have implemented this in following way mentioned below.

one way im thinking is i thought i would not listen to the childevent changes instead i would query the results and populate recyclerview later not listening to child events so that way everything states as it is and i dont know in firebase how do you retrieve values without implementing listeners I tried the singleValueEventListener that way still the behavior is same rolling back to first item or first fragment

guide me through solution how to get rid of this behavior.

Query query= databasePostsReference.orderByChild("timestamp");

       query.addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {
                List<UserPostPOJO> listposts = new ArrayList<UserPostPOJO>();
                for(DataSnapshot snapshot : dataSnapshot.getChildren()){
                    Log.d(TAG, "onDataChange: entered list adding");
                    UserPostPOJO post = 
                    snapshot.getValue(UserPostPOJO.class);
                    listposts.add(0,post);
                }
                if(listposts.isEmpty()){
                    empty.setVisibility(View.VISIBLE);
                    recyclerView.setVisibility(View.GONE);
                }
                else
                {
                    empty.setVisibility(View.GONE);
                    recyclerView.setVisibility(View.VISIBLE);
                    makelist(listposts);
                }


            }

            @Override
            public void onCancelled(DatabaseError databaseError) {

            }
        }); 




private void makelist(List<UserPostPOJO> listposts) {
        list = listposts;
        Log.d(TAG,"size is "+ list.size()+"");

        recyclerView.setHasFixedSize(true);
        recyclerView.setLayoutManager(new 
        LinearLayoutManager(getActivity()));
        CustomRecyclerViewAdapter adapter = new 
        CustomRecyclerViewAdapter(getActivity(), list,"recentfragment");
        recyclerView.setAdapter(adapter);


    }
Abhilash Reddy
  • 428
  • 1
  • 4
  • 19

3 Answers3

2

There is a method called removeEventListener() that you can call to remove a specific event listener. You get data out from your database and than call this method. So in order to make this work, please use the following code:

databaseReference.removeEventListener(valueEventListener);

In which databaseReference is the reference where you intially put the listener.

For more details please read the offcial doc.

Hope it helps.

Alex Mamo
  • 130,605
  • 17
  • 163
  • 193
  • 1
    waw i completely forgot about that ill read and try to implement thanks for this – Abhilash Reddy May 24 '17 at 18:49
  • Hi Alex I hae tried removing the listeners but still the behaviour is same can you guide me through this. what I have added ,I have taken out the inline listener made a listener object and add following line within the onDataChange method after makelist method within the onDataChange method query.removeEventListener(listener); – Abhilash Reddy May 24 '17 at 23:39
  • The practice is to remove your listener according to the activity life-cycle. Most of the time you need to remove the listener in `onPause()` or `onStop()` methods. But according to your needs you can remove the listener after you queried the database once. The flow is like this: `create the reference -> create the listener -> query -> get the data only once -> remove the listener`. – Alex Mamo May 25 '17 at 07:02
  • I have tried this and now the data doesnot load but the behaviour is still the same it rolls back to first fragment and i tried to debug by putting some log messages and every time some one enters post it is invoking again from mauthstatelistener so i tried to remove mauthstatelistener too but dint workout – Abhilash Reddy May 25 '17 at 16:57
  • What is the error when you are trying to remove the `mAuthStateListener`? – Alex Mamo May 25 '17 at 17:00
  • there is no error but its the behaviour i have finished building my app and this is only thing bugging me – Abhilash Reddy May 25 '17 at 17:35
  • I was calling it two times and was it taking it out only once i had to cal only once that fixed my issue. thanks for the help @Alex – Abhilash Reddy May 26 '17 at 01:51
  • Great Abhilash. Best of luck! – Alex Mamo May 26 '17 at 06:43
0

Firebase has a FirebaseRecyclerAdapter which can be set to a RecyclerView. It takes a DatabaseReference or Query object and handles all the data synchronization between your database and your view.

T double
  • 349
  • 3
  • 12
0

For a database reference object, the same way one can add an event listener, it can also be removed, using removeEventListener.

Instead of creating an anonymous object like this

    Query query= databasePostsReference.orderByChild("timestamp");

    query.addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            List<UserPostPOJO> listposts = new ArrayList<UserPostPOJO>();
            for(DataSnapshot snapshot : dataSnapshot.getChildren()){
                Log.d(TAG, "onDataChange: entered list adding");
                UserPostPOJO post = 
                snapshot.getValue(UserPostPOJO.class);
                listposts.add(0,post);
            }
            if(listposts.isEmpty()){
                empty.setVisibility(View.VISIBLE);
                recyclerView.setVisibility(View.GONE);
            }
            else
            {
                empty.setVisibility(View.GONE);
                recyclerView.setVisibility(View.VISIBLE);
                makelist(listposts);
            }
        }

        @Override
        public void onCancelled(DatabaseError databaseError) {

        }
    }); 

you can create a named object of ValueEventListener and remove it from the database reference object using removeEventListener, at the end of the onDataChange method

    Query query= databasePostsReference.orderByChild("timestamp");

    ValueEventListener valueEventListener = new ValueEventListener() {
        @Override
        public void onDataChange(DataSnapshot dataSnapshot) {
            List<UserPostPOJO> listposts = new ArrayList<UserPostPOJO>();
            for(DataSnapshot snapshot : dataSnapshot.getChildren()){
                Log.d(TAG, "onDataChange: entered list adding");
                UserPostPOJO post = 
                snapshot.getValue(UserPostPOJO.class);
                listposts.add(0,post);
            }
            if(listposts.isEmpty()){
                empty.setVisibility(View.VISIBLE);
                recyclerView.setVisibility(View.GONE);
            }
            else
            {
                empty.setVisibility(View.GONE);
                recyclerView.setVisibility(View.VISIBLE);
                makelist(listposts);
            }

            query.removeEventListener(valueEventListener);
        }

        @Override
        public void onCancelled(DatabaseError databaseError) {

        }
    }); 

    query.addValueEventListener(valueEventListener);

The code inside onDataChange method gets executed only once as the ValueEventListener object is removed as soon as the last line of the method gets executed.