I am creating a social app and as soon as the user opens the app, they are suppose to see random posts that I load from the database.
But I don't see that and I have to click on the Random tab to see the posts. So my guess is that the list isn't populated with data by the time the method readRandPosts(); gets called. It's not showing up as null so I have no clue what's wrong. I've checked multiple answers on here and still found nothing to solve my problem. Can someone please help me see what I'm doing wrong ?
private RecyclerView recyclerView;
private PostAdapter postAdapter;
private List<Post> postLists;
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_home, container, false);
HomeFragment homeFragment = new HomeFragment();
homeFragment.post = post;
//////////////////////////// recycler view //////////////////////////////
recyclerView = (VideoPlayerRecyclerView) view.findViewById(R.id.recyclerview);
LinearLayoutManager layoutManager = new LinearLayoutManager(getContext(), LinearLayoutManager.VERTICAL, false);
//layoutManager.setOrientation(RecyclerView.VERTICAL);
recyclerView.setLayoutManager(layoutManager);
recyclerView.setAdapter(postAdapter);
layoutManager.setReverseLayout(false);
layoutManager.setStackFromEnd(false);
VerticalSpacingItemDecorator itemDecorator = new VerticalSpacingItemDecorator(0);
recyclerView.addItemDecoration(itemDecorator);
postLists = new ArrayList<>();
//postLists.clear();
postAdapter = new PostAdapter(getContext(), postLists);
recyclerView.setAdapter(postAdapter);
progressBar = view.findViewById(R.id.progress_circular);
followingBtn = view.findViewById(R.id.followingBtn);
randomBtn = view.findViewById(R.id.randomBtn);
followingBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
checkFollowing();
Toast.makeText(getContext(), "Following", Toast.LENGTH_SHORT).show();
}
});
randomBtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
readRandPosts();
//Toast.makeText(getContext(), "Random", Toast.LENGTH_SHORT).show();
}
});
readRandPosts();
if (postLists != null) {
//Toast.makeText(getContext(), "not null.", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(getContext(), "Posts are null.", Toast.LENGTH_SHORT).show();
}
return view;
}
private void readRandPosts() {
DatabaseReference reference = FirebaseDatabase.getInstance().getReference("Video_Posts");
FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
reference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
postLists.clear();
for (DataSnapshot snapshot:dataSnapshot.getChildren()) {
Post post = snapshot.getValue(Post.class);
assert post != null;
if (user != null ) {
DatabaseReference dbref = FirebaseDatabase.getInstance().getReference("Follow")
.child(post.getPublisher())
.child("followers")
.child(FirebaseAuth.getInstance().getCurrentUser().getUid());
dbref.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
if (!dataSnapshot.exists()) {
postLists.add(post);
//Collections.shuffle(postLists);
} else {
//postLists.add(post);
Toast.makeText(getContext(), "Nothing to show.", Toast.LENGTH_SHORT).show();
}
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
}
});
} else {
Toast.makeText(getContext(), "User null.", Toast.LENGTH_SHORT).show();
}
}
if(postLists == null ) {
progressBar.setVisibility(View.GONE);
Toast.makeText(getContext(), "No data", Toast.LENGTH_SHORT).show();
}
//Collections.reverse(postLists);
postAdapter.notifyDataSetChanged();
progressBar.setVisibility(View.GONE);
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
}
});
}
It's not showing up as null because you are assigning a new ArrayList to the variable here:
postLists = new ArrayList<>();
So instead of checking for null, you should be checking if the list is empty.
Related
I have a recycler view on my home page which is showing some posts from my db. I'm passing data like userID, username etc., into the adapter but the profile picture URL is always null inside the adapter. If I try to print it inside the fragment it shows the correct value.
My database structure:
PostRecyclerAdapter:
public class PostRecyclerAdapter extends RecyclerView.Adapter<PostRecyclerAdapter.ViewHolder> {
List<PostModel> postList;
Context context;
final private DatabaseReference postRef = FirebaseDatabase.getInstance().getReference("posts");
final private DatabaseReference likeRef = FirebaseDatabase.getInstance().getReference("likes");
final private DatabaseReference usersRef = FirebaseDatabase.getInstance().getReference("users");
public PostRecyclerAdapter(ArrayList<PostModel> postModelArrayList, Context context) {
this.postList = postModelArrayList;
this.context = context;
}
#NonNull
#Override
public ViewHolder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.post_item, parent, false);
return new ViewHolder(view);
}
#Override
public void onBindViewHolder(#NonNull ViewHolder holder, int position) {
// check if post is liked or not
FirebaseAuth mAuth = FirebaseAuth.getInstance();
FirebaseUser user = mAuth.getCurrentUser();
likeRef.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull #NotNull DataSnapshot snapshot) {
// check if current post is liked from this user
if (snapshot.child(holder.id).hasChild(user.getUid())) {
// post is liked form this user
holder.like_btn.setImageResource(R.drawable.ic_thumb_up_filled);
} else {
// post is not liked from this user
holder.like_btn.setImageResource(R.drawable.ic_thump_up_outline);
}
}
#Override
public void onCancelled(#NonNull #NotNull DatabaseError error) {
Toast.makeText(context, "error: " + error, Toast.LENGTH_SHORT).show();
}
});
// Get current post id set username, authorID, profile picture URL, likes and post image URL
holder.id = postList.get(position).getId();
holder.username.setText(postList.get(position).getName());
holder.userID = postList.get(position).getAuthorID();
holder.like_counter_tv.setText(postList.get(position).getLikes());
Glide.with(context).load(postList.get(position).getImgUrl()).into(holder.postImg);
// Load profile picture
String profilePictureUrl = postList.get(position).getProfileImgUrl();
// profilePictureUrl IS ALWAYS NULL
if (profilePictureUrl != null) {
if (!profilePictureUrl.equals("none")) {
Glide.with(context).load(profilePictureUrl).into(holder.profileImage);
}
}
}
#Override
public int getItemCount() {
return postList.size();
}
class ViewHolder extends RecyclerView.ViewHolder {
CardView container;
String id;
TextView username, like_counter_tv;
ImageView postImg;
ImageButton like_btn;
CircleImageView profileImage;
boolean isLiked = false;
String userID;
public void updateLikes(String postID, boolean isNotLiked) {
postRef.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull #NotNull DataSnapshot snapshot) {
String currentLikesToString = snapshot.child(postID).child("likes").getValue().toString();
int currentLikesToInt = Integer.parseInt(currentLikesToString);
if (isNotLiked) {
int newCurrentLikes = currentLikesToInt + 1;
String newCurrentLikesToString = Integer.toString(newCurrentLikes);
// Update likes on Real-time DB
postRef.child(postID).child("likes").setValue(newCurrentLikesToString);
// update likes on TextView
like_counter_tv.setText(newCurrentLikesToString);
} else {
int newCurrentLikes = currentLikesToInt - 1;
String newCurrentLikesToString = Integer.toString(newCurrentLikes);
// Update likes on Real-time DB
postRef.child(postID).child("likes").setValue(newCurrentLikesToString);
// update likes on TextView
like_counter_tv.setText(newCurrentLikesToString);
}
}
#Override
public void onCancelled(#NonNull #NotNull DatabaseError error) {
Toast.makeText(context, "Error: " + error, Toast.LENGTH_SHORT).show();
}
});
}
public ViewHolder(#NonNull View itemView) {
super(itemView);
final FirebaseAuth mAuth = FirebaseAuth.getInstance();
final FirebaseUser user = mAuth.getCurrentUser();
final ConstraintLayout sContainer = itemView.findViewById(R.id.second_container);
profileImage = itemView.findViewById(R.id.user_profile_image);
container = itemView.findViewById(R.id.post_item_container);
username = itemView.findViewById(R.id.post_username);
postImg = itemView.findViewById(R.id.post_image);
like_btn = itemView.findViewById(R.id.likeBtn);
like_counter_tv = itemView.findViewById(R.id.like_counter);
likeRef.keepSynced(true);
profileImage.setOnClickListener(v -> {
Intent intent = new Intent(context, UserProfileActivity.class);
usersRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
for (DataSnapshot snap : snapshot.getChildren()) {
if (snap.child("name").getValue().toString().equals(username.getText().toString())) {
UserProfileActivity.username = username.getText().toString();
UserProfileActivity.userID = snap.child("id").getValue().toString();
break;
}
}
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
Toast.makeText(context, "Error: " + error.getMessage(), Toast.LENGTH_SHORT).show();
}
});
context.startActivity(intent);
});
sContainer.setOnLongClickListener(v -> {
FragmentManager manager = ((AppCompatActivity) context).getSupportFragmentManager();
PostOptionsDialog optionsDialog = new PostOptionsDialog();
optionsDialog.setPostId(id);
if (username.getText().toString().equals(user.getDisplayName())) {
optionsDialog.setAuthor(true);
} else {
optionsDialog.setAuthor(false);
}
optionsDialog.show(manager, "options");
return false;
});
like_btn.setOnClickListener(v -> {
// animate like button when clicked
YoYo.with(Techniques.Shake)
.duration(500)
.repeat(0)
.playOn(like_btn);
isLiked = true;
likeRef.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull #NotNull DataSnapshot snapshot) {
if (isLiked) {
if (snapshot.child(id).hasChild(user.getUid())) {
// post is liked from this user, so user wants to unlike this post
like_btn.setImageResource(R.drawable.ic_thump_up_outline);
likeRef.child(id).child(user.getUid()).removeValue();
isLiked = false;
Toast.makeText(context, "You unliked this meme!", Toast.LENGTH_SHORT).show();
// update likes to DB
updateLikes(id, false);
} else {
// post is not liked from ths user, so the user wants to like this post
like_btn.setImageResource(R.drawable.ic_thumb_up_filled);
likeRef.child(id).child(user.getUid()).setValue("true");
Toast.makeText(context, "You liked this meme!", Toast.LENGTH_SHORT).show();
// update likes to DB
updateLikes(id, true);
}
}
}
#Override
public void onCancelled(#NonNull #NotNull DatabaseError error) {
Toast.makeText(itemView.getContext(), "Error: " + error, Toast.LENGTH_LONG).show();
}
});
});
}
}
}
HomeFragment:
public class HomeFragment extends Fragment {
LoadingDialog progressDialog;
final DatabaseReference postsRef = FirebaseDatabase.getInstance().getReference("posts");
final DatabaseReference usersRef = FirebaseDatabase.getInstance().getReference("users");
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_home, container, false);
final RecyclerView recyclerView = view.findViewById(R.id.home_recycler_view);
final ArrayList<PostModel> postModelArrayList = new ArrayList<>();
final LinearLayoutManager layoutManager = new LinearLayoutManager(getContext());
final RecyclerView.Adapter recyclerAdapter = new PostRecyclerAdapter(postModelArrayList, getContext());
final FirebaseAuth mAuth = FirebaseAuth.getInstance();
final FirebaseUser user = mAuth.getCurrentUser();
layoutManager.setReverseLayout(true);
layoutManager.setStackFromEnd(true);
recyclerView.setAdapter(recyclerAdapter);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(layoutManager);
progressDialog = LoadingDialog.Companion.get(getActivity());
progressDialog.show();
postsRef.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull #NotNull DataSnapshot snapshot) {
progressDialog.hide();
for (DataSnapshot snap : snapshot.getChildren()) {
PostModel postModel = new PostModel();
postModel.setId(snap.child("id").getValue(String.class));
postModel.setImgUrl(snap.child("imgUrl").getValue(String.class));
postModel.setLikes(snap.child("likes").getValue(String.class));
postModel.setName(snap.child("name").getValue(String.class));
// find user id and set profile picture by name
usersRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot1) {
for (DataSnapshot snap1 : snapshot1.getChildren()) {
if (snap1.child("name").getValue(String.class).equals(snap.child("name").getValue(String.class))) {
postModel.setAuthorID(snap1.child("id").getValue(String.class));
postModel.setProfileImgUrl(snap1.child("profileImgUrl").getValue(String.class));
}
}
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
Toast.makeText(getContext(), "Error: " + error.getMessage(), Toast.LENGTH_SHORT).show();
}
});
postModelArrayList.add(postModel);
recyclerAdapter.notifyDataSetChanged();
}
}
#Override
public void onCancelled(#NonNull #NotNull DatabaseError error) {
Toast.makeText(getContext(), "Error: " + error, Toast.LENGTH_SHORT).show();
}
});
return view;
}
}
I have a problem clearing list in fragments. I need to clear the list when happening update in fragment. I already put it in different places but it does not help me.
When an update happens in fragment it shows the same list but that list also add elements from the previous list. If I put list.clear(); in the moment when it rakes arguments from firebase it did not give me needed effect, when I put it in onCreate() method then app gives me error.
public class Favourite extends Fragment {
private RecyclerView recyclerView;
private ArrayList<TourReader1> artistList;
private ToursAdapter1 adapter1;
private DatabaseReference reference,reference2;
String uid;
public Favourite() {
// Required empty public constructor
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (getArguments() != null) {
mParam1 = getArguments().getString(ARG_PARAM1);
mParam2 = getArguments().getString(ARG_PARAM2);
}
FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
//Get current user id
uid = user.getUid();
//Connect to specific point in database Tours
reference = FirebaseDatabase.getInstance().getReference("Tours");
//Create add to method valuelistener or reference which is specific point in database
reference2 = FirebaseDatabase.getInstance().getReference("user").child(uid);
reference.addValueEventListener(valueEventListener);
reference.keepSynced(true);
}
ValueEventListener valueEventListener = (new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot1) {
//get all information from specific point of database
for (DataSnapshot datasnapshot : snapshot1.getChildren()) {
//get current name of starting point from where we recive information from database
String firstname = datasnapshot.getKey();
//valuelistener for another point from database
reference2.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
for (DataSnapshot dSnapshot2:snapshot.getChildren()){
String seconame = dSnapshot2.getKey();
Boolean control = dSnapshot2.child("like").getValue(Boolean.class);
if(control != null&&firstname.equals(seconame) &&control.equals(true)) {
TourReader1 artist = datasnapshot.getValue(TourReader1.class);
artistList.add(artist);
}
}
adapter1.notifyDataSetChanged();
}
#Override
public void onCancelled(#NonNull DatabaseError error) {
}
});
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
artistList = new ArrayList<>();
View rootview = inflater.inflate(R.layout.favourite, container, false);
recyclerView = rootview.findViewById(R.id.list);
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(new LinearLayoutManager(getContext()));
adapter1 = new ToursAdapter1(getContext(), artistList);
recyclerView.setAdapter(adapter1);
GridLayoutManager mGridLayoutManager = new GridLayoutManager(getContext(), 2);
recyclerView.setLayoutManager(mGridLayoutManager);
return rootview;
}
}
You should clear the artistList using artistList.clear() before your for loop in onDataChangeas this list is having the data from the last callback triggered.
Ok, I found the answer myself, I clear my list in the adapter by tourlist.clear() and remove userpoints.keepSynced(true); when like icon is false.
holder.sparkButton.setEventListener(new SparkEventListener() {
#Override
public void onEvent(ImageView button, boolean buttonState) {
FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
String uid = user.getUid();
DatabaseReference userpoints = FirebaseDatabase.getInstance().getReference("user").child(uid);
ToursLike registerDatabase = new ToursLike(true);
if(buttonState){
userpoints.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
if (!dataSnapshot.hasChild(tour.Name)) {
userpoints.child(tour.Name).setValue(registerDatabase);
userpoints.keepSynced(true);
tourList.clear();
}
else{
userpoints.child(tour.Name).child("like").setValue(true);
userpoints.keepSynced(true);
tourList.clear();
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
else{
userpoints.addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
userpoints.child(tour.Name).child("like").setValue(false);
tourList.clear();
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
}
#Override
public void onEventAnimationEnd(ImageView button, boolean buttonState) {
}
#Override
public void onEventAnimationStart(ImageView button, boolean buttonState) {
}
});
}
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;
}
}
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);
}
});
I have the following problem. Posts of other users are coming out fine only one post. But if it's your profile, in the HomeFragment the posts are coming out duplicated and I am not sure why that is.
In my readPosts(); method, if I get rid of this line } else if (mFirebaseUser.getUid().equals(post.getPublisher())) {mPostLists.add(post); it's fine, but then my posts don't show up only the posts of the people I follow. I need mine to show up also in the newsfeed, but just once not duplicated. All of my posts are being duplicated. Same post comes up twice on my feed. Can someone tell me what I am doing wrong?
Something I am doing wrong in my readPosts(); method, but I am not sure what after having played around with it a bunch.
HomeFragment
public class HomeTabLayoutFragment extends Fragment {
private ProgressBar mProgressBar;
private PostAdapter mPostAdapter;
private List<Post> mPostLists;
private FirebaseAuth mFirebaseAuth;
private FirebaseUser mFirebaseUser;
private List<String> mFollowingList;
#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);
SwipeRefreshLayout refreshLayout = v.findViewById(R.id.refresh);
refreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
#Override
public void onRefresh() {
refreshLayout.setRefreshing(false);
}
});
checkIfUserExists();
checkFollowing();
return v;
}
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(mFirebaseAuth.getCurrentUser().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() {
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);
for (String id : mFollowingList) {
if (post != null) {
if (post.getPublisher().equals(id)) {
mPostLists.add(post);
} else if (mFirebaseUser.getUid().equals(post.getPublisher())) {
mPostLists.add(post);
}
}
}
mPostAdapter.notifyDataSetChanged();
mProgressBar.setVisibility(View.GONE);
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
}
Check your inner loop in readPosts(). The loop is based on elements of mFollowingList. This condition has nothing to do with that:
if (mFirebaseUser.getUid().equals(post.getPublisher()))
It will be either true or false for every execution of the internal loop. Therefore, it may add more elements than you want. You probably want to put it in the outer loop, not the inner one - to execute it just once per post.
I'd make some more changes though. The check (post != null) can be done outside the loop. No need to let it loop multiple times for no reason. notifyDataSetChanged() also does not need to be inside any loop, it needs to be called once.
Extra regarding code style :-) - You're using too much indentation. It makes sense to extract things to a separate method for readability, it's a good idea to keep methods short, with descriptive names.
private void readPosts() {
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) {
}
});
}
private boolean shouldAddPost(#NotNull Post post) {
boolean isFollowingPublisher = false;
for (String id : mFollowingList) {
if (post.getPublisher().equals(id)) {
isFollowingPublisher = true;
}
}
boolean isPublisher = post.getPublisher().equals(mFirebaseUser.getUid());
return isFollowingPublisher || isPublisher;
}
private void readPosts() {
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);
for (String id : mFollowingList) {
if (post != null) {
if (post.getPublisher().equals(id)) {
mPostLists.add(post);
}
}
}
if (post != null)
if (mFirebaseUser.getUid().equals(post.getPublisher())) {
mPostLists.add(post);
}
}
mPostAdapter.notifyDataSetChanged();
mProgressBar.setVisibility(View.GONE);
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
}
I have a list that I get from firebase, this list is about posts and what I need is when user like it or unlike it, the list updated through adapter. as I used recyclerview and adapter to show my data after receiving it from firebase. Actually, everything works so fine with me but just this issue when user like or unlike the post it goes crazy. I tried to make a toast to make sure that I'm working with the same position as I expected and it proved me right.
the photo of the post appears and disappears by clicking like button like the vides shows and it does not updating the data in a proper way like it mess with the number of likes
You can find my code below with a video to illustrate the problem I am facing.
I hope somebody can help me out.
private void read_posts() {
DatabaseReference reference = FirebaseDatabase.getInstance().getReference("Posts");
reference.addChildEventListener(new ChildEventListener() {
#Override
public void onChildAdded(#NonNull DataSnapshot dataSnapshot, #Nullable String s) {
//post_models.clear();
Post_Model post_model = dataSnapshot.getValue(Post_Model.class);
post_models.add(post_model);
post_adapter = new Post_Adapter(post_models, getContext());
recyclerviewNewsfeed.setAdapter(post_adapter);
progressBar.setVisibility(View.GONE);
}
#Override
public void onChildChanged(#NonNull DataSnapshot dataSnapshot, #Nullable String s) {
Post_Model post_model = dataSnapshot.getValue(Post_Model.class);
for (int i=0;i<post_models.size();i++){
if(post_models.get(i).getId().equals(post_model.getId())){
post_models.set(i,post_model);
post_adapter.notifyItemChanged(i);
break;
}
}
}
#Override
public void onChildRemoved(#NonNull DataSnapshot dataSnapshot) {
}
#Override
public void onChildMoved(#NonNull DataSnapshot dataSnapshot, #Nullable String s) {
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
}
It's my post adapter
public class Post_Adapter extends RecyclerView.Adapter<Post_Adapter.Viewholder> {
private Context context;
private List<Post_Model> post_models;
FirebaseUser firebaseUser;
List<Like_Model> like_modelList, likeblue_modelList;
View_Photos_Adapter view_Photos_adapter;
boolean userlikeit;
public static int positionn=-1;
public Post_Adapter(List<Post_Model> post_models, Context context) {
this.context = context;
this.post_models = post_models;
}
#NonNull
#Override
public Viewholder onCreateViewHolder(#NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(context).inflate(R.layout.post_item, parent, false);
return new Viewholder(view);
}
#SuppressLint("SetTextI18n")
#Override
public void onBindViewHolder(#NonNull final Viewholder holder, final int position) {
final Post_Model post_model = post_models.get(position);
firebaseUser = FirebaseAuth.getInstance().getCurrentUser();
DatabaseReference referencee = FirebaseDatabase.getInstance().getReference("Posts").child(post_model.getId());
referencee.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
//Toast.makeText(CommentActivity.this, post_id+"", Toast.LENGTH_SHORT).show();
Post_Model post_modell = dataSnapshot.getValue(Post_Model.class);
// Toast.makeText(CommentActivity.this, post_id+"", Toast.LENGTH_SHORT).show();
if (post_modell.getLikeModels() != null) {
for (int i = 0; i < post_modell.getLikeModels().size(); i++) {
if (post_modell.getLikeModels().get(i).getUserid().equals(firebaseUser.getUid())) {
userlikeit = true;
break;
} else {
userlikeit = false;
}
}
} else {
userlikeit = false;
}
//snapshot.getRef().removeValue();
// Toast.makeText(context, userlikeit+"58", Toast.LENGTH_SHORT).show();
//Toast.makeText(CommentActivity.this, comment_models.size()+"", Toast.LENGTH_SHORT).show();
if (userlikeit) {
holder.likebluebtn.setVisibility(View.VISIBLE);
holder.likebtn.setVisibility(View.GONE);
} else {
holder.likebtn.setVisibility(View.VISIBLE);
holder.likebluebtn.setVisibility(View.GONE);
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
if (post_model.getUserid().equals(firebaseUser.getUid())) {
holder.editbtn.setVisibility(View.VISIBLE);
holder.deletebtn.setVisibility(View.VISIBLE);
} else {
holder.editbtn.setVisibility(View.GONE);
holder.deletebtn.setVisibility(View.GONE);
}
holder.editbtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
holder.postTextView.setVisibility(View.GONE);
holder.postEditText.setVisibility(View.VISIBLE);
holder.postEditText.setText(post_model.getPost());
holder.editbtn.setVisibility(View.GONE);
holder.savebtn.setVisibility(View.VISIBLE);
}
});
holder.savebtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Post_Model post_modell = new Post_Model(post_model.getId(), post_model.getUserid()
, holder.postEditText.getText().toString(), post_model.getTime()
, post_model.getCommentModels(), post_model.getPostphotos(), post_model.getLikeModels());
FirebaseDatabase.getInstance().getReference("Posts")
.child(post_model.getId())
.setValue(post_modell);
holder.postTextView.setVisibility(View.VISIBLE);
holder.postEditText.setVisibility(View.GONE);
holder.editbtn.setVisibility(View.VISIBLE);
holder.savebtn.setVisibility(View.GONE);
Toast.makeText(context, "Post has been edited successfully", Toast.LENGTH_SHORT).show();
Intent intent = new Intent(context, NewsfeedActivity.class);
context.startActivity(intent);
((Activity) context).overridePendingTransition(R.anim.slide_in_right, R.anim.slide_in_left);
((Activity) context).finish();
}
});
holder.deletebtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
new AlertDialog.Builder(context)
.setTitle("Delete Post")
.setMessage("Are you sure you want to delete this post?")
// Specifying a listener allows you to take an action before dismissing the dialog.
// The dialog is automatically dismissed when a dialog button is clicked.
.setPositiveButton(android.R.string.yes, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
final DatabaseReference referencee = FirebaseDatabase.getInstance().getReference("Posts")
.child(post_model.getId());
referencee.removeValue();
Toast.makeText(context, "Post deleted successfully", Toast.LENGTH_LONG).show();
Intent intent = new Intent(context, NewsfeedActivity.class);
context.startActivity(intent);
((Activity) context).overridePendingTransition(R.anim.slide_in_right, R.anim.slide_in_left);
((Activity) context).finish();
}
})
// A null listener allows the button to dismiss the dialog and take no further action.
.setNegativeButton(android.R.string.no, null)
.setIcon(android.R.drawable.ic_dialog_alert)
.show();
}
});
firebaseUser = FirebaseAuth.getInstance().getCurrentUser();
like_modelList = new ArrayList<>();
likeblue_modelList = new ArrayList<>();
//Toast.makeText(context, read_likes(post_model.getId())+"", Toast.LENGTH_SHORT).show();
DatabaseReference reference = FirebaseDatabase.getInstance().getReference("Users");
reference.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
User user = snapshot.getValue(User.class);
// Toast.makeText(Create_Coworking_SpaceActivity.this, "111111111", Toast.LENGTH_LONG).show();
if (user.getId().equals(post_model.getUserid())) {
if (user.getImageURL().equals("default")) {
holder.userImage.setImageResource(R.drawable.ic_imgprofile);
} else {
Glide.with(holder.itemView).load(user.getImageURL()).into( holder.userImage);
}
holder.username.setText(user.getUsername());
}
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
if (post_model.getPostphotos() == null) {
holder.postPhotosRC.setVisibility(View.GONE);
} else {
holder.postPhotosRC.setHasFixedSize(true);
holder.postPhotosRC.setLayoutManager(new LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false));
view_Photos_adapter = new View_Photos_Adapter(post_model.getPostphotos(), context);
holder.postPhotosRC.setAdapter(view_Photos_adapter);
}
holder.postTextView.setText(post_model.getPost());
holder.posttimeTextView.setText(post_model.getTime());
holder.commentbtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(context, CommentActivity.class);
intent.putExtra("post_id", post_model.getId());
context.startActivity(intent);
((Activity) context).overridePendingTransition(R.anim.slide_in_right, R.anim.slide_in_left);
}
});
if (post_model.getCommentModels() != null) {
holder.numofcommentsEditText.setText(post_model.getCommentModels().size() + "");
holder.numofcommentsTextView.setText(post_model.getCommentModels().size() + "");
}
final int[] li = {0};
holder.likebtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
like(post_model.getId());
// Post_Adapter.this.notifyItemChanged(position);
positionn=position;
}
});
holder.likebluebtn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//Toast.makeText(context, userlikeit+"5", Toast.LENGTH_SHORT).show();
unlike(post_model.getId());
// Post_Adapter.this.notifyItemChanged(position);
positionn=position;
}
});
if (post_model.getLikeModels() != null) {
holder.numoflikesEditText.setText(post_model.getLikeModels().size() + "");
holder.numoflikesTextView.setText(post_model.getLikeModels().size() + "");
}
holder.likesTextView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(context, LikeActivity.class);
intent.putExtra("post_id", post_model.getId());
context.startActivity(intent);
((Activity) context).overridePendingTransition(R.anim.slide_in_right, R.anim.slide_in_left);
}
});
holder.commentsTextView.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Intent intent = new Intent(context, CommentActivity.class);
intent.putExtra("post_id", post_model.getId());
context.startActivity(intent);
((Activity)
context).overridePendingTransition(R.anim.slide_in_right,
R.anim.slide_in_left);
}
});
}
#Override
public int getItemCount() {
return post_models == null ? 0 : post_models.size();
}