1

나는 FragmentRetainInstance sample.을 읽고있다. RetainedFragment mWorkFragmentUiFragment에있다. 그렇다면 화면을 회전 한 후에 UiFragment을 메모리에서 어떻게 삭제할 수 있습니까? 내가 이해하는 한, mWorkFragment은 화면 회전 및 기타 구성 변경에서 생존하는 것에 대한 참조입니다. 1UI 조각에서 유지 된 단편에 대한 참조입니다. 화면을 회전 한 후에 UI 조각을 메모리에서 어떻게 삭제할 수 있습니까?

업데이트 # 나는 화면을 회전 GC를 시작 누르면, 다음 덤프 힙을 눌렀습니다. 나는 UiFragment 인스턴스의 수가 1 인 것을 보았습니다. 왜? 나는 현재 오리엔테이션에 대해 2 : 1을보고 이전 오리엔테이션에 대해 1을 볼 것으로 예상했다.

enter image description here

힙 덤프 :

가 GC 시작 나는 내 댓글에 말했듯이

enter image description here

+0

'UiFragment'가 유지되지 않습니다. 그것이 유지되면 호스트 활동이 재 작성 될 때 다시 생성되지 않습니다. 이것은'Fragment # setRetainInstance (...)'가 작동하는 방식입니다. 따라서 screen과 init a gc를 회전 시키면, 이전의'UiFragment' 인스턴스는 가비지 컬렉션되어야합니다. –

+0

* 메모리에서 UiFragment를 삭제할 수있는 방법 * - GC는 GC 루트 (해당 UiFragment 인스턴스가 아닌)에서 시작한 다음 참조를 트래버스 (등)하여 개체가 여전히 필요한지 확인합니다. 따라서 UiFragment 인스턴스에 대한 참조를 보유하고있는 객체가 오래 살아 있지 않기 때문에 mWorkFragment 참조가 적용되지 않습니다. – Luksprog

+0

@Luksprog, 귀하의 의견에서 알 수 있듯이, GC는 루트 (가능하면 클래스'Application')에서 시작하여 객체를 가로 지르고'UiFragment'가 도달 할 수 없다고 결정합니다 (구성 변경 후 참조가 없습니다). 그래서 그것은 삭제 될 수 있습니다. 'UiFragment'는 도달 할 수없는 서브 트리의 루트이고'mWorkFragment'는'UiFragment'의 자식입니다. 루트에 도달 할 수 없으면 모든 자식에 도달 할 수 없습니다. 권리? –

답변

1

을, 당신이 링크 된 샘플에서 UiFragment은 아니다 누출. 그것은 실제로 구성 변경을 견디는 RetainedFragment에 대한 참조를 보유하지만 그 참조는 중요하지 않습니다. GC는 GC 루트에서 시작하여 오브젝트 내부에서 발견되는 참조를 따라 오브젝트를 탐색합니다. UiFragment는 (RetainedFragment와 마찬가지로) 살아있는 것으로부터 참조되지 않기 때문에 살아있는 객체의 계층 구조를 벗어나 가비지 컬렉션을받을 수 있습니다.

메모리 누수를 보려면 연결된 샘플에서 mProgressBar = null;에서 from RetentionFragment의 onDetach() 콜백. 이 변경으로 RetainedFragment는 UiFragment에 대한 참조를 보유합니다 (실제로 모든 데이터와 함께 이전 활동 임). RetainedFragment의 onActivityCreated() 콜백이 호출 될 때까지 이전 Context 인스턴스를 활성 상태로 유지합니다 (onActivityCreated() mProgressBar가 지워지고 복원 된 UiFragment의 ProgressBar를 가리 키도록 만듭니다.