Android 片段中的RecyclerView泄漏父活动

Android 片段中的RecyclerView泄漏父活动,android,android-fragments,memory-leaks,android-recyclerview,android-adapter,Android,Android Fragments,Memory Leaks,Android Recyclerview,Android Adapter,在我的应用程序中,我有一个包含3个片段的查看页面的主活动。其中两个片段有一个由一些CardView填充的RecyclerView。一切正常,但在安装canary leaks后,我注意到我的RecyclerViews正在泄漏主要活动: 看起来应该有静态引用来阻止GC完成他的工作,但在我的代码中没有这样的东西。我试过打电话 recyclerView.setAdapter(null) or recyclerView.cleanup() 在我的片段的onDestroy/onDestroyView上,但

在我的应用程序中,我有一个包含3个片段的查看页面的主活动。其中两个片段有一个由一些CardView填充的RecyclerView。一切正常,但在安装canary leaks后,我注意到我的RecyclerViews正在泄漏主要活动:

看起来应该有静态引用来阻止GC完成他的工作,但在我的代码中没有这样的东西。我试过打电话

recyclerView.setAdapter(null) or recyclerView.cleanup()
在我的片段的onDestroy/onDestroyView上,但泄漏仍然存在

这是我的片段:

 @Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {     

   //here some FirebaseDatabasereference

    recyclerView = (RecyclerView)inflater.inflate(R.layout.event_fragment_layout, container,false);
    recyclerView.setHasFixedSize(true);
    recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
    return recyclerView;

} 

public void onStart() {
    super.onStart();

    firebaseRecyclerAdapter = new FirebaseRecyclerAdapter<Event, MyEventViewHolder>(

            Event.class,
            R.layout.event_card,
            MyEventViewHolder.class,
            myDatabase.child("Events").orderByChild(ordering[orderingSelector]),

    ) {
        @Override
        protected void populateViewHolder(final MyEventViewHolder viewHolder, final Event model, final int position) {
        final String post_key = getRef(position).getKey();

            viewHolder.setEventName(model.getEventName());
            viewHolder.setEventImage(getApplicationContext(),model.getEventImagePath());

            ValueEventListener likeCheckerListener = new ValueEventListener() {
                @Override
                public void onDataChange(DataSnapshot dataSnapshot) {
                    if(dataSnapshot.child(post_key).hasChild(currentUser.getUid())){
                        viewHolder.setThumbDown();
                        mDatabaseLike.removeEventListener(this);
                    }else{
                        viewHolder.setThumbUp();
                        mDatabaseLike.removeEventListener(this);
                    }
                    mDatabaseLike.removeEventListener(this);
                }

                @Override
                public void onCancelled(DatabaseError databaseError) {

                }
            };
            mDatabaseLike.addValueEventListener(likeCheckerListener);

recyclerView.setAdapter(firebaseRecyclerAdapter);
}

 @Override
public void onStop() {
    super.onStop();
    recyclerView.setAdapter(null);
}

@Override
public void onDestroy() {
    super.onDestroy();
    recyclerView.setAdapter(null);
}

@Override
public void onDestroyView() {
    super.onDestroyView();
    recyclerView.setAdapter(null);
}

我不知道这是否有用,但泄漏通常是从14KB到最大50KB。我已经能够解决所有其他泄漏,但这一次让我发疯了

你的recyclerView是静态的吗?
无论如何,您应该在onDestroyView中将recyclerView设置为null(
recyclerView=null
)(它在onCreateView中初始化)。

您的recyclerView是静态的吗?
无论如何,您应该在onDestroyView中将recyclerView设置为null(
recyclerView=null
)(因为它在onCreateView中初始化)。

我认为问题在于以下调用:

mDatabaseLike.addValueEventListener(likeCheckerListener);
您可以简单地对其进行评论,看看泄漏是否仍在发生

您的likeCheckerListener是匿名类的对象,该类引用了通过重写FirebaseRecyclerAdapter创建的匿名类,FirebaseRecyclerAdapter引用了您的活动。这导致了泄漏

为了能够安全地处理此场景,您应该为添加到mDatabase的每个ValueEventListener维护一个引用,并在onStop/onDestroy方法中删除它们

为此,您可能应该为您的侦听器和他们正在侦听的键维护一个映射


还考虑重写FiBaseReCyrEnter适配器的OnVIEWReCyReCd()方法,然后也可以在视图被回收时逐个删除侦听器,并且只侦听实际需要的项上的事件。

< P>我认为问题是以下调用:

mDatabaseLike.addValueEventListener(likeCheckerListener);
您可以简单地对其进行评论,看看泄漏是否仍在发生

您的likeCheckerListener是匿名类的对象,该类引用了通过重写FirebaseRecyclerAdapter创建的匿名类,FirebaseRecyclerAdapter引用了您的活动。这导致了泄漏

为了能够安全地处理此场景,您应该为添加到mDatabase的每个ValueEventListener维护一个引用,并在onStop/onDestroy方法中删除它们

为此,您可能应该为您的侦听器和他们正在侦听的键维护一个映射


还考虑重写FiBaseReCyrEnter适配器的OnVIEWReCyReCd()方法,然后也可以在视图被回收时逐个删除侦听器,只在实际需要的项上侦听事件。

我的DealReVIEW不是静态的,我已经尝试调用OnDeStYy中的RealReVIEW。SETAdvad(NULL),onDestroView和onStop()如果未成功,则应设置recyclerView=null和adapter firebaseRecyclerAdapter=null。我的recyclerView不是静态的,我已尝试分别在onDestoy、onDestroView和onStop()中调用recyclerView.setAdapter(null)如果未成功,则应将recyclerView=null和adapter firebaseRecyclerAdapter=null。您还可以在onDestroy中调用
recyclerAdapter.cleanup()
。此问题类似于:,但在您的情况下,
recyclerAdapter.setAdapter(null)
没有帮助。感谢您在@OnDestroyViewy中调用recyclerAdapter.cleanup()显然起到了作用。您也可以在onDestroy中调用
recyclerAdapter.cleanup()
。此问题类似于:,但在您的案例中,
recyclerView.setAdapter(null)
没有帮助。感谢您,调用@onDestroyViewmy likeCheckerListener中的recyclerAdapter.cleanup()显然起到了作用,因为在dataSnapshot块中使用ref.RemovelListener(This)将其删除,正如我在上面所评论的,解决方案是调用setAdapter(null)是的,你是对的。我不知道为什么我没有看到;)我的likeCheckerListener在dataSnapshot块中与ref.RemovelListener(this)一起被删除,正如我在上面所评论的,解决方案是调用setAdapter(null)和cleanup()。是的,您是对的。我不知道为什么我没有看到;)