2011-03-23 9 views
4

기초 -보기 + 태그 = 메모리 누출?

  • 활동 각 재생성합니다 (에서 onCreate-들의 OnDestroy)는
  • 보기 두 차일와 ViewFlipper 구성 변경 orientatin : 간단한 RelativeLayout의 및 ListView에
  • ListView에 행이 복잡한 레이아웃과 관련된 태그

문제는 각 방향 변경시 메모리 누수가 발생한다는 것입니다. 전체보기 레이아웃이 메모리에 남아 있습니다. 액티비티 자체는 컨텍스트이므로 관련 객체가 유지되는 한 메모리에 남아 있습니다. 그래서 지금 누수가 발생하는 이유를 찾으려고합니다.

보기가 setTag() 메소드입니다. 행에 대한 정보를 저장하는 데 사용하고 있습니다 (ListView의 모든 행 (뷰)에 태그가 연결되어 있음).

하지만 뷰와 GC는 태그를 어떻게 사용합니까? 내 태그 객체 (소지자)는 뷰에 대한 참조를 포함하지만 뷰에서 태그에 대한 참조를 제거하면이 참조가 (태그 자체로) 쉽게 수집됩니다.

누구나 ListView에서 비슷한 문제가 발생 했습니까?

P. 순환 참조, 컨텍스트, 소지자 등의 레이아웃을 GC가 어떻게 정리하는지 궁금합니다.

답변

3

오리엔테이션 변경 작업에 대한 누수가 쉽습니다. 그냥 조심하려는 onRetainNonConfigurationInstance 방법에 슈퍼 간단히 말해서

http://ttlnews.blogspot.com/2010/01/attacking-memory-problems-on-android.html

http://android-developers.blogspot.com/2009/01/avoiding-memory-leaks.html

http://code.google.com/p/android/issues/detail?id=2391

: 내가 느끼는 필요한 읽기있다 - 이것에 대해 블로그 게시물의 소수가 있습니다 View 객체에 대한 참조를 무시하고 차례로 활동 참조, 진행 표시 줄 등을 생략합니다.

좋은 패턴 나는 우리입니다. e는 Activity 참조를 포함하는 "StateHolder"내부 클래스를 가졌지 만 NULL을 전달하는 setActivityForTasks 메서드를 구현합니다. 그러면 모든 Activity 참조가 NULL로 설정됩니다. 방향 변경 후 활동으로 돌아 가면 setActivityForTasks(this)으로 전화하면 현재 활동을 재설정 할 수 있습니다.

단일 테이크 아웃은 항상 자신의 주변 객체 인스턴스에 대한 포인터를 저장 난 당신이 어딘가에 약간의 비 정적 내부 클래스가있을 수 있습니다 생각 onRetainNonConfigurationInstance

4

에 관련된 어떤 활동에 대한 참조를 밖으로 NULL입니다. 예를 들어 :

public class A { 

    private class B { 
     // ... 
    } 

    // b stores a reference to the instance of A 
    private B b = new B(); 
} 

당신이 (예를 들어, ViewHolder 클래스의 경우)의 SetTag() 메소드를 사용하는 경우가 부모 객체에 대한 참조를 저장하지 않습니다. 사실이 클래스를 정적으로 선언해야합니다.

또한 메모리 누수를 피하기 위해 가능한 경우 항상 getApplicationContext() 결과를 Context가 필요한 메소드에 전달해야하며 Activity 자체에 대한 참조는 전달하지 않아야합니다.

9

View.setTag(int, Object) 방법을 사용하면 먼저 개체를 유출 할 수 있습니다. 이 방법을 사용하여 설정된 태그는 WeakHashMapView을 키로 저장합니다. 따라서 부모 뷰의 태그에 하위 뷰에 대한 참조를 저장하면 이러한 모든 뷰와 함께 생성 된 컨텍스트 (부모 작업)가 유출됩니다. 이는 모든 하위 뷰가 상위 뷰에 대한 참조를 보유하므로 부모 뷰가 GC에 의해 수집되지 않기 때문에 발생합니다.

public static class MainActivity extends ListActivity { 
    private final WeakHashMap<Parent, Parent.Child> mMap = 
     new WeakHashMap<Parent, Parent.Child>(); 

    @Override 
    public void onCreate(final Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 

     // If parents were collected OOM error wouldn't be thrown. 
     // But they aren't collected so we get OOM here. 
     for (int i = 0; i < 10; ++i) { 
      Parent parent = new Parent(); 
      mMap.put(parent, parent.mChild); 
     } 
    } 
} 

public static class Parent { 
    public final Child mChild = new Child(); 

    public class Child { 
     private final byte[] mJunk = new byte[10*1024*1024]; 
    } 
} 

이 두 번째로는 ListView 클래스는 메모리 누수가 발생 것 같다 :

이 동작을 시뮬레이션 할 수있는 간단한 방법이있다. 이는 목록보기, 모든 재활용 된 하위 항목 및 상위 활동이 유출되었음을 의미합니다. 다음은이 버그에 대한 몇 가지 정보는 다음과 같습니다 안드로이드의 진저 브레드에서

+1

내가 틀렸다고 정정하되, 태그가 SparseArray에 저장되었다고 생각합니다. –

+0

@MM. 네가 맞다. 키가있는 태그에 뷰를 저장하는 것이 지금 위험하지는 않습니다. 의견을 주셔서 감사합니다. – Michael

2

낮은 버전, View.setTag (int key, Object tag) 메모리 누수가. 사용하지 마십시오. ICS에서 수정되었습니다.