막무가내 삽질 블로그

안드로이드 액티비티 + 프래그먼트 생명주기 상태정리 본문

Android

안드로이드 액티비티 + 프래그먼트 생명주기 상태정리

joong~ 2020. 2. 10. 11:27
728x90

틀린 부분 있다면 댓글로 남겨주세요

 

 

 

프래그먼트의 add, replace 와 backstack을 사용했을 때 생명주기를 정리해보았다.

 

replace 기존 fragment를 detach까지 끝낸 다음 새로운 fragment를 올림

add 기존 fragment를 그대로 둔 채 새로운 fragment를 올림

 

 

 

테스트 예제 1.  ( fragment add )

액티비티 위에 1~3번의 프래그먼트가 있다는 가정

액티비티 위에 1번 > 2번 > 3번의 순서로 테스트 진행

add.commit을 했을 경우 hide를 안시키면 이미 생성한 프래그먼트라서 에러가 뜬다.

그래서 보이지 않는 프래그먼트는 hide 시켜줬다.

        Button button = findViewById(R.id.btn_one);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (one == null) {
                    one = new FragmentOne();
                    getSupportFragmentManager().beginTransaction().add(R.id.framelaytout, one).commit();
                }

                if (one != null) getSupportFragmentManager().beginTransaction().show(one).commit();
                if (two != null) getSupportFragmentManager().beginTransaction().hide(two).commit();
                if (three != null) getSupportFragmentManager().beginTransaction().hide(three).commit();
            }
        });

위 로그처럼 add를 시켰을 경우 resume에서 멈추게 된다. 1~3번 프레그먼트가 모두 추가된 상태에서 프래그먼트 끼리 계속 이동하게 되면 프래그먼트 매니저가 hide,show를 판단하여 계속 바꾸게 된다.

 

 

 

테스트 예제 2.  ( fragment replace)

액티비티 위에 1번 > 2번 > 3번의 순서로 테스트 진행

        Button button = findViewById(R.id.btn_one);
        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                getSupportFragmentManager().beginTransaction().replace(R.id.framelaytout,one).commit();
            }
        });

replace는 프래그먼트가 이동될 때 마다 기존 프래그먼트를 detach까지 하는 걸 볼 수 있다.

add방식은 가끔 겹치는 현상이 있을 수 있으며 액티비티가 죽을 때 onDetach를 호출하지 않을 때가 있다고 한다.

 

 

 

테스트 예제 3.  ( fragment replace + backstack )

액티비티 위에 1번 > 2번 > 3번 > 백키(2번) > 백키(1번)

        Button button1 = findViewById(R.id.btn_two);
        button1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                getSupportFragmentManager().beginTransaction().replace(R.id.framelaytout,two).addToBackStack("").commit();
            }
        });

3번 프래그먼트까지의 이동은 테스트2번과 비슷하다.

포커스가 3번 프래그먼트에 맞춰진 상태에서 백키를 눌렀을 때 테스트2번 같은경우는 백스택에 프래그먼트가 저장이 되지 않으므로 홈으로 이동되면서 액티비티와 프래그먼트가 onPause, onStop이 호출된다.

하지만 테스트3번은 프래그먼트가 백스택에 저장되므로 3번 프래그먼트가 onPuase ~ onDetach 가 호출되고

그 전 스택인 2번 프래그먼트가 다시 onCreateView를 호출한다.

 

2번 테스트와 3번 테스트의 틀린점 ( 1 ~ 3번 프래그먼트 까지의 이동 )

틀린점은 replace만 했을 경우는 프래그먼트가 onDestroyView - onDestroy - onDetach 까지 되면서 액티비티와 연결이 완전 끊어진걸 볼 수 있다. 백스택에 프래그먼트를 보관했을 때는 onDestroyView 까지만 처리된다. 그러고 해당 프래그먼트가 다시 포커스가 맞춰지면 정의된 view들을 다시 inflate 하기 위해 onCreateView부터 호출된다.

 

 

 

결론 : UI가 있는 프래그먼트는 replace로 처리하는 게 효율적 일거 같다. (첫 프래그먼트만 add, 나머지 replace 처리를 해도 detach까지 호출되는 것을 확인) add로 처리를 하면 hide,show,remove를 사용하여 처리를 해야하므로 코드적으로 길고 복잡해 질 것 같다. replace가 add+remove를 함께 처리해줘서 replace를 많이 사용한다고 한다.

프래그먼트를 UI가 없게 만들어서 백그라운드 작업을 하도록 사용할 수도 있는데 그때는 add를 통해 사용한다고 한다.

(onCreateView가 다시 그려지지 않기 때문, 사용해보지 않았지만 나중에 사용해봐야겠다)

상황에 맞게 잘 사용하자

Comments