카카오맵 API를 사용해 프래그먼트에 현위치를 기반으로 지도를 불러오는 코드 작성 중,
해당 프래그먼트 화면에 진입하지 못하고 이전 액티비티로 다시 돌아가며 아래와 같은 에러 메세지가 떴다.
java.lang.RuntimeException: Unable to start activity ComponentInfo{…} java.lang.IllegalStateException: Fragment not attached to a context.
이 때 코드에서 Fragment에서는 this를 사용할 수 없으니, context를 사용해야 할 곳에 다음 코드처럼 모두 requireContext()를 사용했다.
val locationProvider = LocationProvider(requireContext())
Toast.makeText(requireContext(), error.message, Toast.LENGTH_SHORT).show()
에러 메세지에서 확인할 수 있듯이, Fragment가 아직 액티비티에 연결되어 있지 않은 상태에서 requireContext() 메서드를 호출하였기 때문에 발생한 에러이다.
즉, 이 에러는 Fragment가 부모 Activity에 더 이상 연결되어 있지 않은 상태에서 Fragment의 컨텍스트(context)에 접근하려고 할 때 발생한다.
Fragment가 액티비티에 연결되어 있는지 확인한 후,
해당 메서드나 컨텍스트 관련 작업을 수행애햐 한다.
private val startZoomLevel = 15
private lateinit var startPosition: LatLng
val locationProvider = LocationProvider(requireContext())
val uLatitude = locationProvider.getLocationLatitude()
val uLongtitude = locationProvider.getLocationLongitude()
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
binding = FragmentHomeBinding.inflate(layoutInflater)
// 현재 로그인한 사용자 가져오기
user = Firebase.auth.currentUser
Log.d("MyTag", "HomeFragment user info: ${user}")
checkAllPermissions()
return binding.root
}
위의 코드는 requireContext()를 사용한 수정 전 코드이고, 현재 문제 해결에 필요한 코드만 부분으로 잘라왔다. 이를 다음과 같이 수정한다.
mActivity를 전역변수로 선언 후,
onAttach()에서 인자로 넘겨진 context를 사용해
mActivity를 초기화하여 requireContext()를 mActivity로 수정해준다.
private lateinit var mActivity: MainActivity
val locationProvider = LocationProvider(mActivity)
override fun onAttach(context: Context) {
super.onAttach(context)
mActivity = context as MainActivity
}
💡 onAttach()
Fragment의 생명주기 중, onAttach() 콜백 메소드는 FragmentManager에 추가가되고 이후에 주인 Activity에 attach 될 때 호출된다.
이 시점에서 프래그먼트는 활성화되고 FragmentManager가 프레그먼트의 생명주기 state를 관리한다.
또한 findFragmentById()같은 FragmentMaanger 메소드가 프레그먼트를 반환한다.
인자로 context가 주어진다.
수정한 코드
private lateinit var mActivity: MainActivity
private val startZoomLevel = 15
private lateinit var startPosition: LatLng
val locationProvider = LocationProvider(mActivity)
val uLatitude = locationProvider.getLocationLatitude()
val uLongtitude = locationProvider.getLocationLongitude()
override fun onAttach(context: Context) {
super.onAttach(context)
mActivity = context as MainActivity
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
binding = FragmentHomeBinding.inflate(layoutInflater)
// 현재 로그인한 사용자 가져오기
user = Firebase.auth.currentUser
Log.d("MyTag", "HomeFragment user info: ${user}")
checkAllPermissions()
return binding.root
}