JMB
JMB

Reputation: 313

SwipeRefreshLayout refreshes RecyclerView without having to pull down

I am trying to implement an SwipeRefreshLayout into my app. What I want to happen is that when the user opens the app initially that the data is retrieved from Firebase without having to pull down the layout so the data refreshes. After that, if the user wants to see new data they have to pull down the layout so the RecyclerView is refreshed with new posts that other users have uploaded.

The problem that I am running into is that when I upload a post from my emulator it pops up on screen automatically on my phone without me having to pull down. That's not what I want. First, initial opening of app data should be retrieved automatically without pull down. After that, every time you want to see new data, if I go to a different fragment and then come back the data shouldn't be refreshed unless I pull down.

The code that I have currently is the following. Can someone tell me why it isn't working the way that I would like it to?

I am relatively sure that it's because of my notifyDataSetChanged(); in my readPosts(); method, but I'm not sure how to fix it... Should I just remove it from readPosts(); and add it to the mSwipeRefreshLayout.post...Runnable?

HomeFragment

public class HomeTabLayoutFragment extends Fragment implements SwipeRefreshLayout.OnRefreshListener {

    private ProgressBar mProgressBar;
    private PostAdapter mPostAdapter;
    private List<Post> mPostLists;

    private FirebaseAuth mFirebaseAuth;
    private FirebaseUser mFirebaseUser;

    private List<String> mFollowingList;

    private SwipeRefreshLayout mSwipeRefreshLayout;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View v = inflater.inflate(R.layout.fragment_home_tab_layout, container, false);

        mFirebaseAuth = FirebaseAuth.getInstance();
        mFirebaseUser = FirebaseAuth.getInstance().getCurrentUser();

        mProgressBar = v.findViewById(R.id.progress_circular);

        RecyclerView recyclerView = v.findViewById(R.id.recycler_view);
        recyclerView.setHasFixedSize(true);
        LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getContext());
        linearLayoutManager.setReverseLayout(true);
        linearLayoutManager.setStackFromEnd(true);
        recyclerView.setLayoutManager(linearLayoutManager);
        mPostLists = new ArrayList<>();
        mPostAdapter = new PostAdapter(getContext(), mPostLists);
        recyclerView.setAdapter(mPostAdapter);

        mSwipeRefreshLayout = v.findViewById(R.id.refresh);
        mSwipeRefreshLayout.setOnRefreshListener(this);
        mSwipeRefreshLayout.post(() -> {
            mSwipeRefreshLayout.setRefreshing(true);
            readPosts();
        });

        checkIfUserExists();
        checkFollowing();

        return v;
    }

    @Override
    public void onRefresh() {
        readPosts();
    }

    private void checkIfUserExists() {
        if (mFirebaseAuth == null) {
            Intent intent = new Intent(getContext(), RegisterActivity.class);
            startActivity(intent);
        }
    }

    private void checkFollowing() {
        mFollowingList = new ArrayList<>();
        DatabaseReference reference = FirebaseDatabase.getInstance().getReference("Follow").child(mFirebaseUser.getUid()).child("Following");
        reference.addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
                mFollowingList.clear();
                for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
                    mFollowingList.add(snapshot.getKey());
                }

                readPosts();
            }

            @Override
            public void onCancelled(@NonNull DatabaseError databaseError) {

            }
        });
    }

    private void readPosts() {
        mSwipeRefreshLayout.setRefreshing(true);
        DatabaseReference reference = FirebaseDatabase.getInstance().getReference("Posts");
        reference.addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
                mPostLists.clear();
                for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
                    Post post = snapshot.getValue(Post.class);
                    if (post != null && shouldAddPost(post)) {
                        mPostLists.add(post);
                    }
                }

                mPostAdapter.notifyDataSetChanged();
                mProgressBar.setVisibility(View.GONE);
            }

            @Override
            public void onCancelled(@NonNull DatabaseError databaseError) {

            }
        });

        mSwipeRefreshLayout.setRefreshing(false);
    }

    private boolean shouldAddPost(@NotNull Post post) {
        boolean isFollowingPublisher = false;
        for (String id : mFollowingList) {
            if (post.getPublisher().equals(id)) {
                isFollowingPublisher = true;
                break;
            }
        }

        boolean isPublisher = post.getPublisher().equals(mFirebaseUser.getUid());

        return isFollowingPublisher || isPublisher;
    }
}

Upvotes: 0

Views: 77

Answers (1)

SpiritCrusher
SpiritCrusher

Reputation: 21043

That is because you are using a addValueEventListener. In this case a ValueEventListener will get called each time any changes made in this hierarchy.

You should be using addListenerForSingleValueEvent if you want data only once. In other words if you do not want realtime updates for a node then you use addListenerForSingleValueEvent.

->Answer about mSwipeRefreshLayout.setRefreshing(false) positioning inside readPost .

Right now how you added mSwipeRefreshLayout.setRefreshing(true) and mSwipeRefreshLayout.setRefreshing(false) is actually useless . It will call immediately.. What you should be doing is changing the state inside listeners.

private void readPosts() {
    mSwipeRefreshLayout.setRefreshing(true);
    DatabaseReference reference = FirebaseDatabase.getInstance().getReference("Posts");
    reference.addValueEventListener(new ValueEventListener() {
        @Override
        public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
            mPostLists.clear();
            for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
            Post post = snapshot.getValue(Post.class);
            if (post != null && shouldAddPost(post)) {
                mPostLists.add(post);
            }
        }
            mPostAdapter.notifyDataSetChanged();
            mProgressBar.setVisibility(View.GONE);
            mSwipeRefreshLayout.setRefreshing(false);
        }

        @Override
        public void onCancelled(@NonNull DatabaseError databaseError) {
            mSwipeRefreshLayout.setRefreshing(false);
        }
    });

Upvotes: 1

Related Questions