Reputation: 313
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
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