【问题标题】:RecyclerView in fragment leaking parent Activity片段泄漏父Activity中的RecyclerView
【发布时间】:2017-07-09 17:08:08
【问题描述】:

在我的应用程序中,我有一个 MainActivity,其 ViewPage 由 3 个片段组成。其中两个 Fragment 有一个 RecyclerView 由一些 CardView 填充。一切正常,但在安装金丝雀泄漏后,我注意到我的 RecyclerViews 正在泄漏 MainActivity:

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

recyclerView.setAdapter(null) or recyclerView.cleanup()

在我的 Fragment 的 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);
}

这是我的 ViewHolder :

public class MyEventViewHolder extends RecyclerView.ViewHolder{

View mView;
CircularImageView cardProfile;
TextView cardLikes,cardDate,cardTime;
TextView event_name,joiners,etaMedia,maleSex,cardPrice,femaleSex;
FABRevealLayout mFABRevealLayout;
Button chiudi;
FloatingActionButton fabLike;



public MyEventViewHolder(View itemView) {
    super(itemView);
    mView=itemView;


    //removed some UI declaration and methods for readability
    cardTime = (TextView)mView.findViewById(R.id.cardTime);

    fabLike = (FloatingActionButton)mView.findViewById(R.id.fabLike);

}


public void setThumbUp (){
    fabLike.setImageResource(R.drawable.white_star_empty_24);
}
public void setThumbDown (){
    fabLike.setImageResource(R.drawable.white_star_full_24);
}

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

【问题讨论】:

  • 您也可以在 onDestroy 中调用recyclerAdapter.cleanup()。此问题类似于:github.com/firebase/FirebaseUI-Android/issues/244,但在您的情况下,recyclerView.setAdapter(null) 无济于事。
  • 感谢这显然是通过在@onDestroyView 中调用 recyclerAdapter.cleanup() 来实现的

标签: android android-fragments memory-leaks android-recyclerview android-adapter


【解决方案1】:

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

【讨论】:

  • 我的 recyclerView 不是静态的,我尝试在 onDestoy、onDestroView 和 onStop() 中分别调用 recyclerView.setAdapter(null) 没有成功
  • 你应该设置 recyclerView = null 和适配器 firebaseRecyclerAdapter = null。
【解决方案2】:

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

mDatabaseLike.addValueEventListener(likeCheckerListener);

你可以简单地评论它,看看是否仍然发生泄漏。

您的 likeCheckerListener 是 Anonymous 类的对象,它具有对通过覆盖 FirebaseRecyclerAdapter 创建的 Anonymous 类的引用,该类具有对您的活动的引用。这会导致泄漏。

为了能够安全地处理这种情况,您应该为添加到您的 mDatabase 的每个 ValueEventListener 维护一个引用,并在您的 onStop/onDestroy 方法中将它们全部删除。

为此,您可能应该为您的听众维护一张地图以及他们正在收听的密钥。

还可以考虑重写 FirebaseRecyclerAdapter 的 onViewRecycled() 方法,然后你也可以在视图被回收时一一移除监听器,只监听实际需要的项目上的事件。

【讨论】:

  • 我的 likeCheckerListener 在 dataSnapshot 块中被 ref.removeListener(this) 删除,正如我在上面评论的那样,解决方案是调用 setAdapter(null) AND cleanup()
  • 是的,你是对的。我不知道为什么我没有看到 ;)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-07-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-06-01
  • 2018-03-24
相关资源
最近更新 更多