Leak canary显示我的Activity存在泄漏,但我不理解这个泄漏的原因。
我尝试从Activity中删除部分内容以确定泄漏的来源,但没有什么作用。我甚至将Activity的所有内容都删除了,但仍然得到相同的结果。经过这些测试和其他许多测试,我认为在将我发送到PostDetailActivity
的Activity中存在问题,不知道我的判断正确吗?
我是新手,请原谅我的实现方式。
以下是Activity的代码:
public class PostDetailActivity extends AppCompatActivity {
//details of user and post
String myUid, myName, myProfilPic, postId, pLikes, pDislike, pTitle, pTime, pImage, pUserPic, pUserName;
private DatabaseReference likesRef;
private DatabaseReference dislikeRef;
boolean mProcessLike = false;
boolean mProcessDislike = false;
Integer position, dislike, like;
//post views
ImageView userPicture, postImage;
TextView userName, postTime, postTitle;
Button likeBtn, dislikeBtn, shareBtn;
LinearLayout profileLayout, emptyRecycler, commentExtraSpace;
public RecyclerView recyclerView;
NestedScrollView scrollView;
public static List<Comment> commentList;
CommentAdapter commentAdapter;
//add comments views;
EditText commentEt;
ImageButton sendCommentBtn;
ImageView userCommentImage;
Comment replyComment;
@Override
protected void onCreate(Bundle savedInstanceState) {
// DARK/LIGHT THEME CODE START
if (DarkThem) {
setTheme(R.style.DarkTheme);
} else {
setTheme(R.style.LightTheme);
}
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_post_detail);
myUid = FirebaseAuth.getInstance().getCurrentUser().getUid();
likesRef = FirebaseDatabase.getInstance().getReference().child("Likes");
dislikeRef = FirebaseDatabase.getInstance().getReference().child("Dislikes");
Toolbar toolbar = findViewById(R.id.toolBar);
setSupportActionBar(toolbar);
getSupportActionBar().setTitle("");
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
PostFragment.relogPost(position);
onBackPressed();
}
});
//getting post info with intent
Intent intent = getIntent();
postId = intent.getStringExtra("postId");
pLikes = intent.getStringExtra("pUp");
pDislike = intent.getStringExtra("pDown");
pTitle = intent.getStringExtra("pTitle");
pTime = intent.getStringExtra("pTime");
pImage = intent.getStringExtra("pImage");
pUserPic = intent.getStringExtra("uDp");
pUserName = intent.getStringExtra("uName");
try {
String positionList = intent.getStringExtra("position");
position = Integer.parseInt(positionList);
} catch (Exception e) {
}
//initializing views post
userPicture = findViewById(R.id.userPic);
postImage = findViewById(R.id.pImage);
userName = findViewById(R.id.userNamePost);
postTime = findViewById(R.id.pTime);
postTitle = findViewById(R.id.pTitle);
likeBtn = findViewById(R.id.upBtn);
dislikeBtn = findViewById(R.id.dwnBtn);
shareBtn = findViewById(R.id.shareBtn);
profileLayout = findViewById(R.id.profileLayout);
recyclerView = findViewById(R.id.recyclerView);
scrollView = findViewById(R.id.scrollView);
emptyRecycler = findViewById(R.id.emptyRecycler);
commentExtraSpace = findViewById(R.id.commentExtraSpace);
//initializing views comment
commentEt = findViewById(R.id.commentEt);
sendCommentBtn = findViewById(R.id.sendComment);
userCommentImage = findViewById(R.id.userCommentImage);
//convert time to dd//mm//yyyy hh:mm am/pm
Calendar calendar = Calendar.getInstance(Locale.getDefault());
calendar.setTimeInMillis(Long.parseLong(pTime));
String pTimeshown = DateFormat.format("dd/MM/yyyy hh:mm aa", calendar).toString();
//set data for PostDetails
userName.setText(pUserName);
postTime.setText(pTimeshown);
postTitle.setText(pTitle);
likeBtn.setText(pLikes);
dislikeBtn.setText(pDislike);
//Set user pic
if (pUserPic.equals("default")) {
userPicture.setImageResource(R.mipmap.ic_launcher_round);
} else {
try {
Glide.with(this).load(pUserPic).into(userPicture);
} catch (Exception e) {
}
}
//Setting postPicture
if (pImage.equals("default")) {
postImage.setImageResource(R.drawable.sunset);
} else {
try {
Glide.with(this).load(pImage).into(postImage);
} catch (Exception e) {
}
}
setLikes(postId);
setDislike(postId);
loadComments();
sendCommentBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
sendComment();
commentList.add(replyComment);
commentAdapter.notifyDataSetChanged();
scrollView.post(new Runnable() {
@Override
public void run() {
scrollView.scrollTo(0, recyclerView.getBottom());
}
});
}
});
dislikeBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
pDislike = dislikeBtn.getText().toString();
pLikes = likeBtn.getText().toString();
mProcessDislike = true;
dislikeRef.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
if (mProcessDislike) {
if (dataSnapshot.child(postId).hasChild(myUid)) {
//already disliked ,so remove dislike
dislikeRef.child(postId).child(myUid).removeValue();
mProcessDislike = false;
dislikeBtn.setText(MessageFormat.format("{0}", Integer.parseInt(pDislike) - 1));
postList.get(position).setpDown("" + (Integer.parseInt(pDislike) - 1));
dislike = Integer.parseInt(pDislike) - 1;
postList.get(position).setpDown("" + dislike);
dislikeBtn.setCompoundDrawablesRelativeWithIntrinsicBounds(R.drawable.ic_downvote_black, 0, 0, 0);
} else {
//not liked
likesRef.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
//verifying is user has liked the post
if (dataSnapshot.child(postId).hasChild(myUid)) {
likesRef.child(postId).child(myUid).removeValue();
dislikeRef.child(postId).child(myUid).setValue("-1");
likeBtn.setText(MessageFormat.format("{0}", Integer.parseInt(pLikes) - 1));
postList.get(position).setpUp("" + (Integer.parseInt(pLikes) - 1));
dislike = Integer.parseInt(pDislike) + 1;
dislikeBtn.setText(MessageFormat.format("{0}", dislike));
postList.get(position).setpDown("" + dislike);
} else {
dislikeRef.child(postId).child(myUid).setValue("-1");
dislike = Integer.parseInt(pDislike) + 1;
dislikeBtn.setText(MessageFormat.format("{0}", dislike));
postList.get(position).setpDown("" + dislike);
}
mProcessDislike = false;
dislikeBtn.setCompoundDrawablesRelativeWithIntrinsicBounds(R.drawable.ic_disliked, 0, 0, 0);
likeBtn.setCompoundDrawablesRelativeWithIntrinsicBounds(R.drawable.ic_upvote_black, 0, 0, 0);
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
}
});
}
}
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
}
});
}
});
likeBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
pDislike = dislikeBtn.getText().toString();
pLikes = likeBtn.getText().toString();
mProcessLike = true;
likesRef.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
if (mProcessLike) {
if (dataSnapshot.child(postId).hasChild(myUid)) {
//already liked ,so remove like
likesRef.child(postId).child(myUid).removeValue();
like = Integer.parseInt(pLikes) - 1;
mProcessLike = false;
likeBtn.setText(MessageFormat.format("{0}", like));
postList.get(position).setpUp("" + like);
likeBtn.setCompoundDrawablesRelativeWithIntrinsicBounds(R.drawable.ic_upvote_black, 0, 0, 0);
} else {
//not liked
dislikeRef.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
//verifying is user has dislkied the post
if (dataSnapshot.child(postId).hasChild(myUid)) {
dislikeRef.child(postId).child(myUid).removeValue();
likesRef.child(postId).child(myUid).setValue("1");
dislikeBtn.setText(MessageFormat.format("{0}", Integer.parseInt(pDislike) - 1));
postList.get(position).setpDown("" + (Integer.parseInt(pDislike) - 1));
like = Integer.parseInt(pLikes) + 1;
likeBtn.setText(MessageFormat.format("{0}", like));
postList.get(position).setpUp("" + like);
dislikeBtn.setCompoundDrawablesRelativeWithIntrinsicBounds(R.drawable.ic_downvote_black, 0, 0, 0);
} else {
likesRef.child(postId).child(myUid).setValue("1");
like = Integer.parseInt(pLikes) + 1;
likeBtn.setText(MessageFormat.format("{0}", like));
postList.get(position).setpUp("" + like);
}
mProcessLike = false;
likeBtn.setCompoundDrawablesRelativeWithIntrinsicBounds(R.drawable.ic_liked, 0, 0, 0);
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
}
});
}
}
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
}
});
}
});
scrollView.post(new Runnable() {
@Override
public void run() {
scrollView.scrollTo(0, commentExtraSpace.getBottom());
}
});
DatabaseReference databaseReference = FirebaseDatabase.getInstance().getReference().child("Users").child(myUid);
databaseReference.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
myProfilPic = "" + dataSnapshot.child("imageURL").getValue();
myName = "" + dataSnapshot.child("username").getValue();
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
}
});
}
private void sendComment() {
String comment = commentEt.getText().toString().trim();
//checking if empty
if (TextUtils.isEmpty(comment)) {
Toast.makeText(this, getString(R.string.EmptyComment), Toast.LENGTH_SHORT).show();
return;
}
String timeStamp = String.valueOf(System.currentTimeMillis());
DatabaseReference databaseReference = FirebaseDatabase.getInstance().getReference("Comments");
HashMap<String, String> hashMap = new HashMap<>();
//put info in hashmap
hashMap.put("commentId", timeStamp);
hashMap.put("comment", comment);
hashMap.put("timeStamp", timeStamp);
hashMap.put("userId", myUid);
hashMap.put("userPicture", myProfilPic);
hashMap.put("userName", myName);
hashMap.put("like", "0");
hashMap.put("dislike", "0");
hashMap.put("replies", "no");
hashMap.put("liked", "no");
hashMap.put("disliked", "no");
databaseReference.child(postId).child(timeStamp).setValue(hashMap);
replyComment = new Comment(timeStamp, comment, timeStamp, "noid", myProfilPic, myName, "0", "0", "no", "no", "no");
commentEt.setText("");
}
private void loadComments() {
//linear layout for recyclerView
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(getApplicationContext());
//set layout to recyclerView
recyclerView.setHasFixedSize(true);
recyclerView.setLayoutManager(linearLayoutManager);
//init comments list
commentList = new ArrayList<>();
//path of the post,to get comments;
DatabaseReference databaseReference = FirebaseDatabase.getInstance().getReference("Comments").child(postId);
databaseReference.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
commentList.clear();
for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
Comment comment = snapshot.getValue(Comment.class);
if (snapshot.child("comments").getChildrenCount() >= 1) {
comment.setReplies("" + snapshot.child("comments").getChildrenCount());
} else {
comment.setReplies("no");
}
if (snapshot.child("likes").hasChild(myUid)) {
comment.setLiked("yes");
} else {
comment.setLiked("no");
}
if (snapshot.child("dislikes").hasChild(myUid)) {
comment.setDisliked("yes");
} else {
comment.setDisliked("no");
}
comment.setLike(String.valueOf(snapshot.child("likes").getChildrenCount()));
comment.setDislike(String.valueOf(snapshot.child("dislikes").getChildrenCount()));
commentList.add(comment);
//setup adapter
}
commentAdapter = new CommentAdapter(PostDetailActivity.this, commentList, postId);
//set adapter
if (commentAdapter.getItemCount() > 0) {
recyclerView.setAdapter(commentAdapter);
emptyRecycler.setVisibility(View.GONE);
} else {
recyclerView.setVisibility(View.GONE);
emptyRecycler.setVisibility(View.VISIBLE);
}
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
}
});
}
private void setLikes(final String postKey) {
likesRef.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
if (dataSnapshot.child(postKey).hasChild(myUid)) {
//user has liked this post
//indicate it with new design
likeBtn.setCompoundDrawablesRelativeWithIntrinsicBounds(R.drawable.ic_liked, 0, 0, 0);
} else {
//user has not liked
likeBtn.setCompoundDrawablesRelativeWithIntrinsicBounds(R.drawable.ic_upvote_black, 0, 0, 0);
}
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
}
});
}
private void setDislike(final String postKey) {
dislikeRef.addListenerForSingleValueEvent(new ValueEventListener() {
@Override
public void onDataChange(@NonNull DataSnapshot dataSnapshot) {
if (dataSnapshot.child(postKey).hasChild(myUid)) {
//user has liked this post
//indicate it with new design
dislikeBtn.setCompoundDrawablesRelativeWithIntrinsicBounds(R.drawable.ic_disliked, 0, 0, 0);
} else {
//user has not liked
dislikeBtn.setCompoundDrawablesRelativeWithIntrinsicBounds(R.drawable.ic_downvote_black, 0, 0, 0);
}
}
@Override
public void onCancelled(@NonNull DatabaseError databaseError) {
}
});
}
@Override
public boolean onSupportNavigateUp() {
onBackPressed();
return super.onSupportNavigateUp();
}
@Override
public void onBackPressed() {
// PostFragment.recyclerView.getAdapter().notifyItemChanged(position);
if (isTaskRoot() && getSupportFragmentManager().getBackStackEntryCount() == 0) {
finishAfterTransition();
} else {
super.onBackPressed();
}
}
}
┬───
│ GC Root: System class
│
├─ android.app.ActivityThread class
│ Leaking: NO (a class is never leaking)
│ ↓ static ActivityThread.sCurrentActivityThread
│ ~~~~~~~~~~~~~~~~~~~~~~
├─ android.app.ActivityThread instance
│ Leaking: UNKNOWN
│ ↓ ActivityThread.mNewActivities
│ ~~~~~~~~~~~~~~
├─ android.app.ActivityThread$ActivityClientRecord instance
│ Leaking: UNKNOWN
│ ↓ ActivityThread$ActivityClientRecord.nextIdle
│ ~~~~~~~~
├─ android.app.ActivityThread$ActivityClientRecord instance
│ Leaking: UNKNOWN
│ ↓ ActivityThread$ActivityClientRecord.activity
│ ~~~~~~~~
╰→ com.RLD.newmemechat.PostDetailActivity instance
Leaking: YES (ObjectWatcher was watching this because com.RLD.newmemechat.PostDetailActivity received Activity#onDestroy() callback and Activity#mDestroyed is true)
key = 533b7987-0f38-41f4-9f1a-e468dcf83264
watchDurationMillis = 8537
retainedDurationMillis = 3530~~~