I'm using Recycle Adapter class and using this to populate the fragments with blog image and description. But when I close the BlogActivity and move to Next Activity then sometimes suddenly app get crashed with error of
java.lang.IllegalArgumentException:You cannot start a load for a destryoed activity at com.bumptech.glide.manager.RequestManagerRetriever.asseertNotDestroyed(RequestManagerRetriver.java:312)
My Recycle adapter classs code is
package com.nepalpolice.cdp;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Build;
import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
import android.text.format.DateFormat;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.PopupWindow;
import android.widget.TextView;
import android.widget.Toast;
import com.bumptech.glide.Glide;
import com.bumptech.glide.request.RequestOptions;
import com.google.android.gms.tasks.OnCompleteListener;
import com.google.android.gms.tasks.Task;
import com.google.firebase.auth.FirebaseAuth;
import com.google.firebase.firestore.DocumentSnapshot;
import com.google.firebase.firestore.EventListener;
import com.google.firebase.firestore.FieldValue;
import com.google.firebase.firestore.FirebaseFirestore;
import com.google.firebase.firestore.FirebaseFirestoreException;
import com.google.firebase.firestore.QuerySnapshot;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import de.hdodenhof.circleimageview.CircleImageView;
import static com.android.volley.VolleyLog.TAG;
import static com.nepalpolice.cdp.webfaq.isNetworkStatusAvialable;
public class BlogRecyclerAdapter extends RecyclerView.Adapter<BlogRecyclerAdapter.ViewHolder> {
public List<BlogPost> blog_list;
public Context context;
private FirebaseFirestore firebaseFirestore;
private FirebaseAuth firebaseAuth;
private PopupWindow popWindow;
public BlogRecyclerAdapter(List<BlogPost> blog_list){
this.blog_list = blog_list;
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.blog_list_item, parent, false);
context = parent.getContext();
firebaseFirestore = FirebaseFirestore.getInstance();
firebaseAuth = FirebaseAuth.getInstance();
return new ViewHolder(view);
}
@Override
public void onBindViewHolder(final ViewHolder holder, int position) {
holder.setIsRecyclable(false);
final String blogPostId = blog_list.get(position).BlogPostId;
final String currentUserId = firebaseAuth.getCurrentUser().getUid();
String desc_data = blog_list.get(position).getDesc();
holder.setDescText(desc_data);
String image_url = blog_list.get(position).getImage_url();
String thumbUri = blog_list.get(position).getImage_thumb();
holder.setBlogImage(image_url, thumbUri);
String user_id = blog_list.get(position).getUser_id();
//User Data will be retrieved here...
firebaseFirestore.collection("Users").document(user_id).get().addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() {
@Override
public void onComplete(@NonNull Task<DocumentSnapshot> task) {
if(task.isSuccessful()){
String userName = task.getResult().getString("name");
String userImage = task.getResult().getString("image");
holder.setUserData(userName, userImage);
} else {
//Firebase Exception
}
}
});
try {
long millisecond = blog_list.get(position).getTimestamp().getTime();
String dateString = DateFormat.format("MM/dd/yyyy", new Date(millisecond)).toString();
holder.setTime(dateString);
} catch (Exception e) {
Toast.makeText(context, "Exception : " + e.getMessage(), Toast.LENGTH_SHORT).show();
}
//Get Likes Count
firebaseFirestore.collection("Posts/" + blogPostId + "/Likes").addSnapshotListener(((Main2Activity) context),new EventListener<QuerySnapshot>() {
@Override
public void onEvent(QuerySnapshot documentSnapshots, FirebaseFirestoreException e) {
if (e!=null) {
Log.w(TAG, "listening failed",e);
return;
}
if(!documentSnapshots.isEmpty()){
int count = documentSnapshots.size();
holder.updateLikesCount(count);
} else {
holder.updateLikesCount(0);
}
}
});
//Get Likes
firebaseFirestore.collection("Posts/" + blogPostId + "/Likes").document(currentUserId).addSnapshotListener(((Main2Activity) context),new EventListener<DocumentSnapshot>() {
@Override
public void onEvent(DocumentSnapshot documentSnapshot, FirebaseFirestoreException e) {
if (e!=null) {
Log.w(TAG, "listening failed",e);
return;
}
if (documentSnapshot.exists()){
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
holder.blogLikeBtn.setImageDrawable(context.getDrawable(R.mipmap.action_like_accent));
}
else {
holder.blogLikeBtn.setImageDrawable(context.getResources().getDrawable(R.mipmap.action_like_accent));
}
} else {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
holder.blogLikeBtn.setImageDrawable(context.getDrawable(R.mipmap.action_like_gray));
}else{
holder.blogLikeBtn.setImageDrawable(context.getResources().getDrawable(R.mipmap.action_like_gray));
}
}
}
});
//Likes Feature
holder.blogLikeBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
firebaseFirestore.collection("Posts/" + blogPostId + "/Likes").document(currentUserId).get().addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() {
@Override
public void onComplete(@NonNull Task<DocumentSnapshot> task) {
if(!task.getResult().exists()){
Map<String, Object> likesMap = new HashMap<>();
likesMap.put("timestamp", FieldValue.serverTimestamp());
firebaseFirestore.collection("Posts/" + blogPostId + "/Likes").document(currentUserId).set(likesMap);
} else {
firebaseFirestore.collection("Posts/" + blogPostId + "/Likes").document(currentUserId).delete();
}
}
});
}
});
holder.blogCommentBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent commentIntent = new Intent(context, CommentsActivity.class);
context.startActivity(commentIntent);
}
});
}
@Override
public int getItemCount() {
return blog_list.size();
}
public class ViewHolder extends RecyclerView.ViewHolder {
private View mView;
private TextView descView;
private ImageView blogImageView;
private TextView blogDate;
private TextView blogUserName;
private CircleImageView blogUserImage;
private ImageView blogLikeBtn;
private TextView blogLikeCount;
private ImageView blogCommentBtn;
public ViewHolder(View itemView) {
super(itemView);
mView = itemView;
blogLikeBtn = mView.findViewById(R.id.blog_like_btn);
blogCommentBtn = mView.findViewById(R.id.blog_comment_icon);
}
public void setDescText(String descText){
descView = mView.findViewById(R.id.blog_desc);
descView.setText(descText);
}
public void setBlogImage(String downloadUri, String thumbUri){
blogImageView = mView.findViewById(R.id.blog_image);
RequestOptions requestOptions = new RequestOptions();
requestOptions.placeholder(R.drawable.image_placeholder);
Glide.with(context).applyDefaultRequestOptions(requestOptions).load(downloadUri).thumbnail(
Glide.with(context).load(thumbUri)
).into(blogImageView);
}
public void setTime(String date) {
blogDate = mView.findViewById(R.id.blog_date);
blogDate.setText(date);
}
public void setUserData(String name, String image){
blogUserImage = mView.findViewById(R.id.blog_user_image);
blogUserName = mView.findViewById(R.id.blog_user_name);
blogUserName.setText(name);
RequestOptions placeholderOption = new RequestOptions();
placeholderOption.placeholder(R.drawable.profile_placeholder);
Glide.with(context).applyDefaultRequestOptions(placeholderOption).load(image).into(blogUserImage);
}
public void updateLikesCount(int count){
blogLikeCount = mView.findViewById(R.id.blog_like_count);
blogLikeCount.setText(count + " Likes");
}
}
}
and my MainActivity code is
public class MainActivity extends AppCompatActivity {
private Toolbar mainToolbar;
private FirebaseAuth mAuth;
private FirebaseFirestore firebaseFirestore;
private String current_user_id;
private FloatingActionButton addPostBtn;
private HomeFragment homeFragment;
private BottomNavigationView mainbottomNav;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mAuth = FirebaseAuth.getInstance();
firebaseFirestore = FirebaseFirestore.getInstance();
mainToolbar = (Toolbar) findViewById(R.id.main_toolbar);
setSupportActionBar(mainToolbar);
getSupportActionBar().setTitle("Central Department of Physics");
mainToolbar.setNavigationOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent newPostIntent = new Intent(Main2Activity.this, MainActivity.class);
startActivity(newPostIntent);
}
});
mainbottomNav = findViewById(R.id.mainBottomNav);
// FRAGMENTS
homeFragment = new HomeFragment();
replaceFragment(homeFragment);
mainbottomNav.setOnNavigationItemSelectedListener(new BottomNavigationView.OnNavigationItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
switch (item.getItemId()){
case R.id.bottom_action_home :
replaceFragment(homeFragment);
return true;
case R.id.bottom_action_account:
return true;
case R.id.bottom_action_notif:
return true;
default:
return false;
}
}
});
addPostBtn = findViewById(R.id.add_post_btn);
addPostBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent newPostIntent = new Intent(Main2Activity.this, NewPostActivity.class);
startActivity(newPostIntent);
}
});
}
@Override
protected void onStart() {
super.onStart();
FirebaseUser currentUser = FirebaseAuth.getInstance().getCurrentUser();
if(currentUser == null){
Intent loginIntent = new Intent(Main2Activity.this, LoginActivity.class);
startActivity(loginIntent);
finish();
} else {
current_user_id = mAuth.getCurrentUser().getUid();
firebaseFirestore.collection("Users").document(current_user_id).get().addOnCompleteListener(new OnCompleteListener<DocumentSnapshot>() {
@Override
public void onComplete(@NonNull Task<DocumentSnapshot> task) {
if(task.isSuccessful()){
if(!task.getResult().exists()){
Intent setupIntent = new Intent(MainActivity.this, SetupActivity.class);
startActivity(setupIntent);
finish();
}
} else {
String errorMessage = task.getException().getMessage();
Toast.makeText(Main2Activity.this, "Error : " + errorMessage, Toast.LENGTH_LONG).show();
}
}
});
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.main_menu, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_logout_btn:
logOut();
return true;
case R.id.action_settings_btn:
Intent settingsIntent = new Intent(MainActivity.this, SetupActivity.class);
startActivity(settingsIntent);
return true;
default:
return false;
}
}
private void logOut() {
mAuth.signOut();
sendToLogin();
}
private void sendToLogin() {
Intent loginIntent = new Intent(MainActivity.this, LoginActivity.class);
startActivity(loginIntent);
finish();
}
private void replaceFragment(Fragment fragment){
FragmentTransaction fragmentTransaction = getSupportFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.main_container, fragment);
fragmentTransaction.commit();
}
}
Here is the complete code https://github.com/akshayejh/PhotoBlog-Android-Blog-App
Workaround, not recommended because it will lead to some unnecessary processing if Activity was destroyed. But it is easy to use and makes its work. In Glide.with (context) try to pass Application context instead of Activity.
Glide loading pictures reported the above error, which may be caused by the incompatibility between the simulator API and glide version This kind of error does not appear on the real machine, but on the genymonitor Failed to deserialize — local class incompatible: stream classdesc serialVersionUID [Solved]
The main idea is that Glide is concerned about lifecycle of an element where it works. If a Fragment or an Activity will be destroyed, Glide finishes its work for image processing. Here is a detailed discussion of the issue. To sum up, you should check if your activity is alive before calling load going back from some AsyncTask or other threads:
The main idea is that Glide is concerned about lifecycle of an element where it works. If a Fragment or an Activity will be destroyed, Glide finishes its work for image processing. Here is a detailed discussion of the issue.
Check whether your activity is finishing before using Glide. Something like this:
if (!activity.isFinishing()) {
Glide.with(...
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With