Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/209.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/image/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 修复泄漏金丝雀发现的活动内存泄漏_Android_Memory Leaks_Leakcanary - Fatal编程技术网

Android 修复泄漏金丝雀发现的活动内存泄漏

Android 修复泄漏金丝雀发现的活动内存泄漏,android,memory-leaks,leakcanary,Android,Memory Leaks,Leakcanary,泄漏金丝雀在我的活动中显示泄漏,但我不了解泄漏的原因 我试图从活动中移除零件,以检查泄漏的来源,但没有成功。我还删除了活动中的所有内容,仍然得到了相同的结果。在这些测试和许多其他测试之后,我假设将我发送到PostDetailActivity的活动中存在错误;还是我错了 我是个新手。很抱歉,活动是如何实施的 这里是活动 您不应在活动中放置firebase数据库引用和侦听器。你应该把它们放在你的viewModel中。这显然是Android框架造成的漏洞。leaktrace中没有与您的代码相关的内容,


泄漏金丝雀在我的活动中显示泄漏,但我不了解泄漏的原因

我试图从活动中移除零件,以检查泄漏的来源,但没有成功。我还删除了活动中的所有内容,仍然得到了相同的结果。在这些测试和许多其他测试之后,我假设将我发送到
PostDetailActivity
的活动中存在错误;还是我错了

我是个新手。很抱歉,活动是如何实施的

这里是活动
您不应在活动中放置firebase数据库引用和侦听器。你应该把它们放在你的viewModel中。

这显然是Android框架造成的漏洞。leaktrace中没有与您的代码相关的内容,我可以告诉您,ActivityThread在ActivityThread.mNewActivities中维护一个ActivityThread$ActivityClientRecord的链接列表

你可以在这里看到:

//应
//下次我们闲着的时候被报告。
ActivityClientRecord mNewActivities=null;
看起来这是由主线程空闲时运行的ActivityThread.Idler完成的:


这用于在创建活动后主线程空闲时通知活动管理器。不幸的是,如果主线程在Activity.onCreate()和Activity.ondestory()之间没有空闲,这似乎会导致泄漏。

您可以共享PostDetailActivity代码吗?@Golnar我已经添加了活动,很抱歉它太乱了。这个泄漏跟踪有点令人惊讶,它显示gc根是一个系统类,但是第一个元素是一个实例而不是一个类。你复制粘贴正确了吗?如果是,您应该在LeakCanary项目上提交一个问题,并提供一个堆转储来帮助调查发生了什么。@Pierre YvesRicau我已重新附加了一个编辑器建议删除的部分。我做了一些更改,但现在还没有得到它,我想我可以复制它。这个由Android框架引起的泄漏是否也是我得到LeakActivity泄漏的泄漏跟踪的原因?泄漏:是的(ObjectWatcher正在监视此事件,因为leakcanary.internal.activity.LeakActivity收到了activity#onDestroy()回调和activity#mDestroyed是真的)可以,但不一定总是查看泄漏跟踪以确定原因。根据我的理解和泄漏跟踪,似乎是相同的原因,非常感谢您的回答!
    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~~~
    private class Idler implements MessageQueue.IdleHandler {
        @Override
        public final boolean queueIdle() {
            ActivityClientRecord a = mNewActivities;
            boolean stopProfiling = false;
            if (mBoundApplication != null && mProfiler.profileFd != null
                    && mProfiler.autoStopProfiler) {
                stopProfiling = true;
            }
            if (a != null) {
                mNewActivities = null;
                IActivityTaskManager am = ActivityTaskManager.getService();
                ActivityClientRecord prev;
                do {
                    if (localLOGV) Slog.v(
                        TAG, "Reporting idle of " + a +
                        " finished=" +
                        (a.activity != null && a.activity.mFinished));
                    if (a.activity != null && !a.activity.mFinished) {
                        try {
                            am.activityIdle(a.token, a.createdConfig, stopProfiling);
                            a.createdConfig = null;
                        } catch (RemoteException ex) {
                            throw ex.rethrowFromSystemServer();
                        }
                    }
                    prev = a;
                    a = a.nextIdle;
                    prev.nextIdle = null;
                } while (a != null);
            }
            if (stopProfiling) {
                mProfiler.stopProfiling();
            }
            applyPendingProcessState();
            return false;
        }
    }