2014-01-08 1 views
1

저는 액티비티 중 90 %가 일반적인 액티비티를 상속하고 이러한 모든 액티비티가 누출되는 애플리케이션에서 작업하고 있습니다. 즉, A->B에서 B->Afinish()이 호출되면 BonDestroy()이 호출되지만 여전히 누수됩니다 (MAT로 확인).메모리 누수 - 안드로이드 활동이 android.os.Message에 의해 개최되었습니다.

누출 된 활동이 꽤 큽니다 (10MB ~). 그래서 몇 차례 앞뒤로 이동 한 후 앱이 OOM으로 중단됩니다.

나는 힙 덤프를 확인하고 누출 활동에 뿌리를 GC의 경로를 따라 그들은 모두 같이했습니다 enter image description here

그래서 나는 새는 공통의 슈퍼 클래스에 뭔가 같아요. 나는 이미 모든 BroadcastReceivers와 청취자가 활동이 파괴되고 아무런 누출을 일으키지 않을 수도있는 익명의 내부 클래스 나 Handler이 없으면 등록을 취소했다는 것을 확인했다.

누출의 원인은 무엇일까요? 어떤 도움이라도 대단히 감사 할 것입니다. ProgressDialog를 인스턴스화 코드의

  1. 일부 라인 :

    편집

    전 주석 때 활동이 더 이상 유출되지 않도록 코드의 두 가지가있는 것으로 나타났습니다.

  2. Runnable의 익명으로 postDelayed으로 전화하십시오. 첫 번째 경우에

는 대화 상자의 dismiss() 기능이 파괴되기 전에 호출되기 때문에이 문제가 될 수 이유를 모르겠어요. 두번째 경우, 에있는 Runnable에 대해 removeCallbacks가 호출되었으므로 이론적으로 제대로 정리 되었습니까?

건배.

+0

첫 번째 샷은 활동의 컨텍스트에 대한 참조를 유지하는 익명 또는 내부 클래스입니다. 활동 코드를 게시하여 살펴볼 수 있습니다. –

+0

불행히도 코드를 공개 할 수 없으며 상당히 거대하고 지저분합니다. MAT 스크린 샷에서 뭐라고 말합니까? – Pin

+1

그것은 당신이 컨텍스트를 유출하고 있으며 메시지 대기열에 보관되어 있다고 알려줍니다. 먼저, 활동에 비 정적 내부 클래스가 있는지 확인하십시오. 정적이 아닌 내부 클래스의 객체는 부모에 대한 참조를 보유하므로 다시 확인해야 할 수 있습니다. 또한 게시하는 실행 파일을 다시 확인하십시오. 실행하는 데 너무 오래 걸립니까? 메시지 대기열에 있으면 활동의 컨텍스트가 삭제되지 않습니다. –

답변

1

문제는 의 익명입니다. postDelayed입니다. 이 Runnable은 기본 활동의 내용보기의 postDelayed() 함수를 호출, 그래서는 다음과 같이이었다 :

@Override 
protected void onResume() { 
    ... 
    mCallback = new Runnable() { ... }; 
    getContentView().postDelayed(mCallback, mDelay); 
} 

놀라운 부분은이 콜백은 onPause()에서 제거되었다 :

@Override 
protected void onPause() { 
    ... 
    getContentView().removeCallbacks(mCallback); 
    mCallback = null; 
} 

이것이 누출을 막지 못했던 이유는 여전히 나에게 미스터리이다. 처음에는 getContentView().getHandler().removeCallbacksAndMessages(null)을 사용해 보았지만 누수가 수정되었지만 그 응용 프로그램은 관련성이없는 것으로 보이는 부분이 완전히 깨졌습니다.

마지막으로 Handler 인스턴스를 만들고이 핸들러에서 postDelayed()removeCallbacks()을 호출하는 것으로 수정되었습니다.

+0

안녕하세요, 정말 미스터리예요. getContentView.postDelayed와 getContentView.removeCallbacks에 의해 반환 된 부울 값을 기록하는 것은 흥미로울 것입니다. View에서 이러한 메소드를 노출하기 위해 정말 나쁜 API 디자인과 같은 것 같습니다. Handler 클래스에서만이 두 메서드를 남겨 두었습니다. 또한 핸들러 구현이 다른 경우에 대비하여 훨씬 강력해질 수 있습니다. –

+0

'removeCallbacks'의 반환 값을 확인했는데 항상 true를 반환했습니다. 아무 것도 분명히 나에게 틀린 것처럼 보였습니다. 나는 API 디자인이 왜 조금 꼴 사나운 지, 왜 그런 기능이 있는지에 대해 동의하지 않는다. – Pin