FragmentFactory로 매개변수가 있는 생성자 안전하게 사용하기

KIMGEUNTAE·2024년 11월 28일
1

Android

목록 보기
10/10

안드로이드 개발에서 Fragment는 화면 구성 요소를 분리하고 재사용성을 높이는 데 중요한 역할을 합니다. 일반적으로 Fragment는 기본 생성자를 사용해야 하지만 개발 과정에서 데이터를 프래그먼트로 전달하기 위해 매개변수가 있는 생성자를 사용하는 경우가 종종 있습니다.

하지만 매개변수가 있는 생성자를 사용하면 구성 변경(Configuration Change) 또는 시스템 재생성 시 문제가 발생할 수 있습니다. 이 글에서는 FragmentFactory를 활용해 이러한 문제를 해결하고 안정적으로 매개변수가 있는 생성자를 사용하는 방법 입니다.


📌 문제 정의

매개변수 생성자를 사용하는 프래그먼트의 문제점

  1. 안드로이드 시스템의 기본 동작:

    • 시스템은 프래그먼트를 재생성할 때 기본 생성자를 호출합니다.
    • 매개변수가 있는 생성자가 있을 경우, 시스템은 이를 인식하지 못해 InstantiationException이 발생합니다.
  2. 에러 로그

    java.lang.RuntimeException: Unable to start activity ComponentInfo
    Caused by: androidx.fragment.app.Fragment$InstantiationException: could not find Fragment constructor
    
  • 이 에러는 기본 생성자가 없을 때 발생하며, 폰트 크기 변경이나 화면 회전 같은 구성 변경 시 앱이 크래시하게 됩니다.
  1. 왜 기본 생성자를 사용해야 하는가?
  • 안드로이드 시스템은 구성 변경(Configuration Changes) 발생 시 Fragment를 재생성하는데, 이때 반드시 파라미터가 없는 기본 생성자를 필요로 합니다. 하지만 현재 구현에는 파라미터가 있는 생성자만 존재하여 시스템이 Fragment를 재생성하지 못하는 상황입니다.

  • 안드로이드 개발자 페이지에도 해당 문서에 확인 하면 이유가 나와있습니다.
    밑에 글이 해당하는 내용의 이유
    https://developer.android.com/reference/android/app/Fragment

    All subclasses of Fragment must include a public no-argument constructor. The framework will often re-instantiate a fragment class when needed, in particular during state restore, and needs to be able to find this constructor to instantiate it. If the no-argument constructor is not available, a runtime exception will occur in some cases during state restore.


📌 해결책: FragmentFactory 사용

1. FragmentFactory란?

  • FragmentFactory는 프래그먼트 생성 과정을 커스터마이징할 수 있는 클래스입니다.
  • 매개변수가 있는 생성자를 안전하게 사용할 수 있도록 지원하며, 의존성 주입과 데이터 전달을 쉽게 구현할 수 있습니다.

2. 문제 부분

class HomeFragment(private val message: String) : Fragment() {
    // 에러 발생: 기본 생성자가 없으므로 시스템 재생성 불가능
}

3. FragmentFactory 설정

class HomeFragmentFactory(private val message: String) : FragmentFactory() {
    override fun instantiate(classLoader: ClassLoader, className: String): Fragment {
        return when (className) {
            HomeFragment::class.java.name -> HomeFragment(message)
            else -> super.instantiate(classLoader, className)
        }
    }
}

4. Fragment 설정

class HomeFragment(private val message: String) : Fragment() {

    private lateinit var binding: FragmentHomeBinding

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View {
        binding = FragmentHomeBinding.inflate(inflater, container, false)
        return binding.root
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        // 메시지 표시
        binding.textView.text = message
    }

}

5. MainActivity에서 FragmentFactory 설정

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        supportFragmentManager.fragmentFactory = HomeFragmentFactory("Test")
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
    }
}


📌 FragmentFactory와 기존 방식의 비교

항목Bundle 사용 방식FragmentFactory 방식
데이터 전달arguments를 사용해 직렬화 데이터 전달생성자를 통해 직렬화되지 않은 데이터 전달 가능
구성 변경 처리상태 저장 및 복원이 필요생성자를 통한 데이터 전달로 상태 복원 가능
의존성 주입직접 구현 필요쉽게 구현 가능
사용 사례단순 데이터 전달복잡한 데이터 또는 의존성 전달

📌 FragmentFactory 사용의 장단점

장점

  1. 매개변수 생성자 지원:

    • 시스템 재생성 시에도 매개변수 생성자를 사용할 수 있습니다.
  2. 유연한 데이터 전달:

    • 직렬화가 필요 없는 객체나 의존성을 주입할 수 있습니다.
  3. 테스트 용이성:

    • 테스트 시, 다양한 데이터를 가진 프래그먼트를 손쉽게 생성할 수 있습니다.

단점

  1. 복잡성 증가:

    • FragmentFactory를 추가로 작성해야 하므로 코드가 약간 복잡해질 수 있습니다.
  2. 기존 코드와의 호환성 문제:

    • 기존 프로젝트의 프래그먼트 관리 방식을 변경해야 할 수 있습니다.

📌 마무리

FragmentFactory를 사용하면 안드로이드 시스템의 기본 생성자 요구 사항을 우회하여 매개변수를 가진 생성자를 안전하게 사용할 수 있다.
이는 구성 변경 및 시스템 재생성 시 발생할 수 있는 크래시 문제를 효과적으로 해결합니다.

언제 사용할까?

  • 데이터 전달이 간단한 경우에는 arguments를 사용하는 것이 더 간단하고 적합할 수 있습니다.
  • 그러나 복잡한 데이터 전달, 의존성 주입, 또는 테스트 환경 구축이 필요한 경우 FragmentFactory를 사용하는 것이 강력한 대안이 된다고 한다.

깃허브 : https://github.com/GEUN-TAE-KIM/Constructors_With_FragmentFactory_Sample


참고
https://developer.android.com/reference/android/app/Fragment
https://developer.android.com/guide/topics/resources/runtime-changes?hl=ko

profile
Study Note

2개의 댓글

comment-user-thumbnail
2024년 11월 29일

안녕하세요! 😊

글 정말 잘 읽어봤어요! FragmentFactory를 이용해서 매개변수가 있는 생성자를 안전하게 사용하는 방법을 깔끔하게 정리해주셨네요! 특히 문제 정의부터 해결책까지 단계별로 설명해주셔서 이해하기 쉬웠어요. 👏👏

하지만 몇 가지 생각해볼 부분이 있어서 조금만 피드백 드릴게요! 🙋‍♂️

  1. 코드 예제에 대한 추가 설명 📝

    코드 블록 사이사이에 간단한 설명이나 주석이 있으면 독자들이 이해하기 더 쉬울 것 같아요. 예를 들어, 각 코드가 어떤 역할을 하는지, 왜 필요한지에 대한 부가 설명이 있으면 좋을 것 같아요. 😊

  2. FragmentFactory 사용의 단점에 대한 구체적인 예시 ⚠️

    단점 부분에서 "기존 코드와의 호환성 문제"를 언급하셨는데, 구체적으로 어떤 문제가 발생할 수 있는지 예시를 들어주시면 더 이해하기 쉬울 것 같아요. 예를 들어, 기존에 arguments를 통해 데이터를 전달하던 방식과 FragmentFactory를 사용하는 방식이 혼용될 때 발생할 수 있는 문제점 등을 설명해주시면 좋을 것 같아요. 🤔

  3. 결론 부분의 보완 🔍

    "언제 사용할까?" 부분에서 조금 더 구체적인 사례를 들어주시면 좋을 것 같아요. 예를 들어, 의존성 주입이 필요한 경우, 복잡한 객체를 전달해야 하는 경우, 테스트를 용이하게 하기 위해 등 구체적인 상황을 제시하면 독자들이 실제로 적용할 때 큰 도움이 될 것 같아요. 😊

  4. 참고 자료의 활용 📚

    참고 자료를 링크해주셨는데, 해당 자료들을 어떻게 활용하면 좋을지에 대한 간단한 설명이 있으면 독자들에게 도움이 될 것 같아요. 예를 들어, "더 자세한 내용은 이 링크를 참고하세요!" 같은 식으로요. 👍

전체적으로 정말 유익한 글이었고, 많은 도움이 되었어요! 앞으로도 좋은 글 많이 부탁드릴게요! 감사합니다! 🙇‍♂️💕

1개의 답글