1

在我的應用程序中,我有一個MainActivity與ViewPage組成3片段。這些碎片中的兩個具有由某些CardView填充的RecyclerView。一切工作正常,但安裝金絲雀泄漏後,我注意到我的RecyclerViews正在泄漏MainActivity:, the last 3 lines of CanaryLeaks look like this :RecyclerView在片段泄漏父項活動

它看起來應該有靜態引用,防止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); 
} 

,這是我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。我已經能夠解決所有其他的泄漏,但這是我的瘋狂

+0

您也可以在onDestroy中調用'recyclerAdapter.cleanup()'。這個問題看起來類似於:https://github.com/firebase/FirebaseUI-Android/issues/244,但在你的情況'recyclerView.setAdapter(null)'沒有幫助。 – marcinj

+1

感謝此顯然工作通過調用recyclerAdapter.cleanup()在@onDestroyView –

回答

0

您的recyclerView是靜態的嗎? 無論如何,你應該在onDestroyView中設置recyclerView爲null(recyclerView = null)(因爲它在onCreateView中初始化)。

+0

我recyclerView不是靜態的,我已經嘗試在onDestoy,onDestroView和onStop()分別調用recyclerView.setAdapter(null) –

+0

你應該設置recyclerView = null和適配器firebaseRecyclerAdapter = null。 – Jagroshan

0

我認爲這個問題是下面的調用:

mDatabaseLike.addValueEventListener(likeCheckerListener); 

你可以簡單地評論一下,看看是否泄漏仍在進行之中。

您的likeCheckerListener是Anonymous類的對象,它具有對通過覆蓋FirebaseRecyclerAdapter創建的Anonymous類的引用,該類引用了您的活動。這會導致泄漏。

爲了能夠安全地處理這種情況,您應該爲添加到您的mDatabase的每個ValueEventListener保留一個引用,並將它們全部移除到onStop/onDestroy方法中。

對於這可能你應該保持一個地圖與你的聽衆和他們正在聽的關鍵。

還可以考慮重寫FirebaseRecyclerAdapter的onViewRecycled()方法,然後您也可以在回收視圖時逐個刪除偵聽器,並只偵聽實際需要的項目上的事件。

+0

我的likeCheckerListener在dataSnapshot塊中被ref.removeListener(this)移除,正如我上面評論的解決方案是調用setAdapter(null)和cleanup() –

+0

是的你是對的。我不知道爲什麼我沒有看到;) – Yunnyyy