출처 - http://blog.naver.com/regako/220261214098
일반 액티비티와 프래그먼트액티비티의 생명주기 차이를 나타내는 플로우 다이어그램은
널리고 널렸으니 제쳐 두고,
이번 포스트는 프래그먼트들을 더하거나(add) 갈아치울 때(replace) 등등의 경우에
각 프래그먼트들에 불리는 method들을 정리해봤다.
기본적으로 프래그먼트 액티비티(Main)가 있고, 여기에 2개의 프래그먼트(F1, F2)를 이리저리
해보면서 직접 로그로 찍어본 결과들이다.
- case 1: Main에 F1을 add로 추가한다.(fragmentManager.beginTransaction().add(id, F1, "f1").commit() - 이후 아래부터는 commit 명령 생략함)
Main onCreate
F1 onAttach
Main onAttachFragment
F1 onCreate
F1 onCreateView
F1 onViewCreated
F1 onActivityCreated
F1 onStart
Main onStart
Main onResume
F1 onResume
Main onResumeFragments
Main onPostResume
* 특이 사항 : onStart는 F1,Main순으로 불리는데 onResume은 그 반대로 불린다.
- case 2: 위 상황에 이어서 back 키로 앱 종료
F1 onPause
Main onPause
F1 onStop
Main onStop
F1 onDestroyView
F1 onDestory
F1 onDetach
Main onDestroy
- case 3: case 1 상황에 이어서 F1을 F2로 replace(fragmentManager.beginTransaction().replace(id, F2, "f2"))
F1 onPause
F1 onStop
F1 onDestroyView
F1 onDestroy
F1 onDetach
F2 onAttach
Main onAttachFragment
F2 onCreate
F2 onCreateView
F2 onViewCreated
F2 onActivityCreated
F2 onStart
F2 onResume
- case 4 : case 1 상황에 이어서 F1을 remove하고 F2를 add(fragmentManager.beginTransaction().remove(F1).add(id,F2,"f2"))
*case 3과 동일. 애초에 replace가 remove+add이므로 당연한 결과라 할 수 있다.
----여기서 추가 조건.
case 5 : Main에서 F1과 F2를 모두 더한 상태로 조건을 수정한다. add F1, add F2 하고 F2를 detach로 숨긴 상황이다.
- case 6 : case 5 상황에 이어서 F1을 detach하고 F2를 attach(fragmentManager.beginTransaction().detach(F1).attach(F2))
F1 onPause
F1 onStop
F1 onDestoryView
F2 onCreateView
F2 onViewCreated
F2 onActivityCreated
F2 onStart
F2 onResume
* 특이사항 : remove, add와의 차이점은 onCreate,onAttach,onDetach,onDestroy가 불리지 않는다는 점이다.
헷갈리기 쉬운데 attach,detach를 사용할 때 오히려 onAttach,onDetach가 안 불리는 걸 주의하자.
- case 7: case 5 상황에 이어서 F1을 hide하고 F2를 show(fragmentManager.beginTransaction().hide(F1).show(F2))
* 아무 api도 호출되지 않음!
* 즉, 모든 fragment가 그냥 모습 그대로 살아있다는 얘기다. 각 프래그먼트들의 전환과 업데이트에 골치가 아플 때
메모리문제만 없으면 이게 제일 속시원한 방법이다.
----여기서 추가 조건.
일반적인 전환이 아니라 addToBackStack(null)을 이용해 스택을 쌓으면서 전환시키는 경우를 살펴본다.
스택을 쌓으며 전환하면 Back동작시에 자동으로 이전 프래그먼트를 보여주는 기능이 있다.
- case 8: 히스토리 스택에 쌓으면서 F1을 F2로 replace(replace(id,F2,"f2").addToBackStack(null))
F1 onPause
F1 onStop
F1 onDestoryView
F2 onAttach
Main onAttachFragment
F2 onCreate
F2 onCreateView
F2 onViewCreated
F2 onActivityCreated
F2 onStart
F2 onResume
- case 9: case 8 상황에서 back으로 F1 pop
F2 getView
F2 onPause
F2 onStop
F2 onDestroyView
F1 onCreateView
F1 onViewCreated
F1 onActivityCreated
F1 onStart
F1 onResume
- case 10: 히스토리 스택에 쌓으면서 F1 detach, F2 attach
F1 onPause
F1 onStop
F1 onDestoryView
F2 onCreateView
F2 onViewCreated
F2 onActivityCreated
F2 onStart
F2 onResume
- case 11: case 10 상황에서 back으로 F1 pop
F2 getView
F2 onPause
F2 onStop
F2 onDestroyView
F1 onCreateView
F1 onViewCreated
F1 onActivityCreated
F1 onStart
F1 onResume
* 특이 사항 : 위 4 경우를 보면, replace(=remove+add)와 detach, attach가 F2 onAttach빼고는 전부 동일하다.
스택에 쌓지 않는 경우에는 replace시에 기존 프래그먼트의 onDetach와 onDestroy가 불리는데, 위 경우에는
그런 게 불리지가 않아 detach, attach와 동일해진 것이다. 스택에 쌓으려면 보관을 해야되니 그렇게 하는 것이
당연할 수도 있겠다.
아 그리고 주의할 점.
FragmentManager는 변수로 빼도 되지만, 실제로 동작을 처리하는 FragmentTransaction은 매번 호출해줘야 한다.
즉 클래스의 멤버변수로
private FragmentManager mFragmentManager=null;
을 선언해놓고 액티비티를 생성할 때 onCreate()에서
mFragmentManager = getSupportFragmentManager();
로 지정해서 여기저기서 사용할 수 있지만, FragmentTransaction은 저렇게 변수로 빼면 안된다.
이후 add,replace의 동작을 할 때는
mFragmentManager.beginTransation().add(blabla).commit();
와 같이 beginTransaction을 꼭 해주어야 함을 기억하자.
위의 모든 명령어의 마지막에는 반드시 commit을 해주는건 기본 상식이다.
번외 1.
FragmentManager는 FragmentActivity(Main)의 getSupportFragmentManager로 얻을 수가 있고,
하위 Fragment(F1)에서 getChildFragmentManager()로도 얻을 수가 있는데, 이 FragmentManager들은
서로 다른 매니저이다. 즉 다수의 프래그먼트매니저를 얻어와서 컨트롤할 수가 있다는 말인데 이런 사례가 있을 수 있겠다.
프래그먼트액티비티안에 4개의 프래그먼트들로 이루어진 탭이 있는데 이 각각의 탭을 전환할때는 Main의
매니저를 이용해 replace를 하고, 하나의 탭에서 히스토리를 쌓아가며 깊게 들어가는 시나리오가 있다면
그 깊게 들어갈때의 프래그먼트 전환을 F1의 매니저로 스택관리를 하는 방법이다.
번외 2.
이건 좀 이상한 현상인데, FragmentManager에서 getFragment()를 하면 List<Fragment>를 반환한다.
근데 replace를 하거나 스택을 쌓은 후 다시 back으로 스택을 없앴을 때 사이즈가 최대값으로 남아있는 현상이다.
예를 들어 F1을 F2로 replace한 후에 다시 F3, F4로 순서대로 스택을 쌓으면서 replace를 한다.
이후에 Back을 두번눌러서 F2로 돌아오면 매니저에 남아있는 fragment는 F2 하나여야 할 거 같은데(다 replace니까)
List<Fragment>.size()를 보면 4로 나온다. 매니저에 한번이라도 등록한건 죽을때까지 가지고 있는 것인가.
그런데 더 이상한 건, getFragments()로 얻어온 결과를 디버깅해서 보면 size는 4인데 분명히 실제값은 1개의 F2만 들어가있는
이해할 수 없는 상황이 벌어져있다는 것이다. 내가 뭘 잘못 알고 있는 건지, 안드로이드의 버그인지, 아니면 의도된 결과인지
전혀 모르겠다. 어쨋든 이점 때문에 히스토리관리를 fragment의 갯수로 하려는 방법은 무산된 상태이다.
[출처] Fragment LifeCycle 메소드 호출 순서|작성자 참지킴이
'개발 > 안드로이드' 카테고리의 다른 글
안드로이드 디자인 서포트 라이브러리 (0) | 2015.07.04 |
---|---|
Android Design Support Library (0) | 2015.06.27 |
[Android] Fragment LifeCycle (프레그먼트 생명주기) (0) | 2015.03.27 |
[Android]WebView를 JavaScript와 연동 (0) | 2015.03.24 |
CustomView 생성시 override 해야 할 function들 (0) | 2015.01.26 |
댓글