I am currently developing a simple social media app that uses Firebase. The user will receive a feed of posts that contain images, his profile image will be displayed in corner of the screen and in the settings activity I created.
The app works fine, apart from a OOM (Out of Memory Exception). After a few minutes of switching activities the images will stop loading. I believe this is caused by memory leaks in my app. I viewed the android profiler and it showed my memory increasingly steadily every time I loaded an image.
I have been stuck on this for quite a while and I really badly need some help. My app won't work if it can only display images for a short period of time. Here is my code, please can someone help:
private void DisplayUserPostsToLayout() {
final FirebaseRecyclerAdapter<postsGetInfo,postsGetInfoViewHolder> firebaseRecyclerAdapter =
new FirebaseRecyclerAdapter<postsGetInfo, postsGetInfoViewHolder>(postsGetInfo.class, R.layout.posts_layout,postsGetInfoViewHolder.class,postRef) {
@Override
protected void populateViewHolder(final postsGetInfoViewHolder viewHolder, postsGetInfo model, int position) {
final String postKey = getRef(position).getKey();
viewHolder.setUsername(model.getUsername());
viewHolder.setTime(model.getTime());
viewHolder.setDate(model.getDate());
viewHolder.setDescription(model.getDescription());
viewHolder.setProfileImage(model.getProfileimage());
viewHolder.setImage(model.getImage());
viewHolder.myView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Intent editIntent = new Intent((getActivity()),postEdit.class);
editIntent.putExtra("PostKey",postKey);
startActivity(editIntent);
}
});
}
};
postList.setAdapter(firebaseRecyclerAdapter);
}
public static class postsGetInfoViewHolder extends RecyclerView.ViewHolder {
View myView;
public postsGetInfoViewHolder(View itemView) {
super(itemView);
myView = itemView;
}
/**/public void setUsername(String username){
TextView Username = (TextView) myView.findViewById(R.id.txtName);
Username.setText(username);
}
public void setProfileImage(String profileImage){
CircularImageView profile = (CircularImageView) myView.findViewById(R.id.profileImage);
Picasso.get().load(profileImage).placeholder(R.drawable.ic_wifi).into(profile);
}
public void setTime(String time){
TextView postTime = (TextView) myView.findViewById(R.id.txtTime);
postTime.setText(time);
}
public void setDate(String date){
TextView postDate = (TextView) myView.findViewById(R.id.txtDate);
postDate.setText(date);
}
public void setDescription(String description){
TextView postDescription = (TextView) myView.findViewById(R.id.txtSurname);
postDescription.setText(description);
}
/**/ public void setImage(String image){
ImageView postImage = (ImageView) myView.findViewById(R.id.imgPost);
Picasso.get().load(image).placeholder(R.drawable.ic_wifi).into(postImage);
}
}
Gradle:
implementation 'com.google.firebase:firebase-auth:11.0.2'
implementation 'com.google.firebase:firebase-database:11.0.2'
implementation 'com.google.firebase:firebase-storage:11.0.2'
implementation 'com.google.android.gms:play-services-auth:11.0.2'
implementation 'com.firebaseui:firebase-ui-database:2.1.1'
There is a newer library but I have already coded my app using these so far.
Adding event listeners without removing them when they're no longer needed, will cause problems over time.
In your particular case, you don't remove a listener when it's no longer needed, so it continue to receive changes that occur at the location where it's listening. In your case, that also means that also Picasso
will continue to load images.
Every time you add a listener like yours without removing it, all the prior listeners will all still receive results and download images. Repeating this many times, will quickly consume the available bandwidth on user's device.
Always be sure to remove listeners that you don't need any more like this:
firebaseRecyclerAdapter.cleanup();
You can also take a look at my answer from this post.