앱 만들기/안드로이드

FragmentContainerView 사용시 주의 사항

나도 처음이야 2022. 8. 14.

FragmentContainerView 를 사용하여 프래그먼트를 생성시 

onCreateView 가 불리지 않고 앱이 죽는다면? 앱을 실행하면 바로 죽는다.

처음에는 도대체 왜 죽는지 한참을 헤멨다.

 

XML에는 하기처럼 코드가 정의되어 있다.

프래그먼트를 프래그먼트 컨테이너 뷰를 이용해서 잘 불러오고 있다.

<androidx.fragment.app.FragmentContainerView
    android:id="@+id/fragment_container_view"
    android:name="bluemooninsea.soo.fragmentstudy.ColorFragment"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    tools:layout="@layout/fragment_color" />

그런데, 앱을 실행 하면 죽는다.

죽는 이유는 MainActivity 에서 하기처럼 프래그먼트 매니지를 통해서 프래그먼트의 로컬 함수를 직접 호출한다.

protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    // 메인액티비티와 프래그먼트의 연결 작업 시작
    // 프래그먼트 컨트롤을 위해서 프래그먼트 매니저를 얻어온다
     fragmentManager = getSupportFragmentManager();
    // findFragmentById() 로 프래그먼트 를 가져옴.
    ColorFragment colorFragment = (ColorFragment) fragmentManager.findFragmentById(R.id.fragment_container_view);
    colorFragment.setColor(Color.RED);
}

문제는 해당 프래그먼트의 로컬 함수에 있다. textView 가 null point 라서 발생하는 문제이다. 

public void setColor(int color){
    textView.setBackgroundColor(color);
}

onCreateView 가 호출되면서 프래그먼트를 인플레이트를 해야하는데,

onCreateView 가 호출되지 않고 죽는 문제가 발생한다. 왜 이럴까?

public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    Log.d("TEST" , "TEST = onCreateView");
    // Inflate the layout for this fragment
    View view =  inflater.inflate(R.layout.fragment_color, container, false);
    textView = view.findViewById(R.id.text);
    return view;
}

 

프래그먼트를 프래그먼트 컨테이너 뷰를 이용해서 호출하면, fragment 내부의 onInflate() 함수를 호출한다.

참고로, 프래그먼트 를 바로 사용한 경우에는 onInflate() 를 호출하지 않고 해당 MainActivity 코드에서도 죽지 않는다.

<androidx.fragment.app.FragmentContainerView
    android:id="@+id/fragment_container_view"
    android:name="bluemooninsea.soo.fragmentstudy.ColorFragment"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    tools:layout="@layout/fragment_color" />

 

그럼, MainActivity 를 하기처럼 바꾸자.

OnCreate 에서는 직접적으로 프래그먼트의 내부 함수 콜을 부르지 않는다.

FragmentManager fragmentManager;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // 메인액티비티와 프래그먼트의 연결 작업 시작
        // 프래그먼트 컨트롤을 위해서 프래그먼트 매니저를 얻어온다
         fragmentManager = getSupportFragmentManager();
        // findFragmentById() 로 프래그먼트 를 가져옴.
        //ColorFragment colorFragment = (ColorFragment) fragmentManager.findFragmentById(R.id.fragment_container_view);
        // colorFragment.setColor(Color.RED);
    }

별도의 함수를 생성해서 버튼 이벤트에 따른 프래그먼트 내부함수를 콜한다.

이렇게 구현하면 FragmentContainerView 코드가 정상적으로 동작한다.

public void changeRed(View view) {
    // findFragmentById() 로 프래그먼트 를 가져옴.
    ColorFragment colorFragment = (ColorFragment) fragmentManager.findFragmentById(R.id.fragment_container_view);
    colorFragment.setColor(Color.RED);
}

 

정리해보면, Activity 와 프래그먼트의 실행 라이프사이클에 답이있다.

액티비티의 oncreate()가 실행되는 시점에 프래그먼트의 onCreateView()난 아직 실행전이라는 이야기다.

FragmentContainerView 를 사용하면 프래그먼트 클래스에서 onCrateView()를 호출전 onInflate() 콜백 함수 의 한단계가 더 진행되기에 인플레이트 되지 않은 프래그먼트의 직접적인 접근이 문제가 되는 것이다.

한참을 헤메다가 스스로 어렵게 수정해 보았다.

편하게 이야기 하자면 삽질 ^^;  스스로 공부하고 생각한 점을 남긴다.

반응형

댓글