오늘의 디버깅 시간~ 디버깅 기초중에 기초라고 할 수 있는? 주제임

 

바로 Context

에서 생기는 오류로 실제로 디버깅 모드에서 avd로 개발 중이거나 할 때는 발견할 일도 많이 없지만, 실제 기기에서 화면 전환이 무자비하게 이뤄지거나, 아니면 쉘몽키 같은걸로 앱을 두들길 때 발견할 수 있음 ㅋㅋ

https://developer.android.com/reference/android/content/Context

 

Context  |  Android Developers

 

developer.android.com

 

not attached to a context. 

라고 로그에 나오는데 공홈에서는 

애플리케이션 환경에 대한 글로벌 정보에 대한 인터페이스입니다. 이것은 안드로이드 시스템에서 구현을 제공하는 추상 클래스입니다. 애플리케이션별 리소스 및 클래스에 대한 액세스는 물론, 액티비티 시작, 브로드캐스팅 및 수신 인텐트 등과 같은 애플리케이션 수준 작업에 대한 업콜을 허용합니다.

라는 설명.

해석하자면 너의 코드중에 어떤게 컨텍스트에 연결돼 있지 않다. ->  구현을 제공하는 추상 클래스가 사라져버렸다 (화면이 꺼져버렸다 or 화면을 그려지고 있는데 너가 먼저 context를 불러냈다 등..)

context 정의 android
context 정의

뭐 여러가지 이유가 있음. 정말 흔하게 생기는데 특히 토스트나 스낵바 같은거 달아놨을 때 자주 생기구요 

 

아래 코드는 내가 특정 버튼이 계속 색이 변하게 강조하는 코드였는데, 릴리즈 모드에서 가끔 삑이 남.. 

Handler(Looper.getMainLooper()).postDelayed({
                   val colorAnimation = ValueAnimator.ofObject(
                       ArgbEvaluator(),
                       ContextCompat.getColor(context, R.color.mainColor),
                       Color.parseColor("#2BEE8C")).apply {
                       duration = 500
                       repeatCount = ValueAnimator.INFINITE
                       repeatMode = ValueAnimator.REVERSE

                        addUpdateListener { animator ->
                          val color = animator.animatedValue as Int
                           binding.btn.backgroundTintList = ColorStateList.valueOf(color)
                      }
                   }
                  colorAnimation.start()
               }, 4000)

그럴 때 어떡하냐.... 

 

let 활용하기 

 

context.let { context ->
           if (context != null) {
               Handler(Looper.getMainLooper()).postDelayed({
                   val colorAnimation = ValueAnimator.ofObject(
                       ArgbEvaluator(),
                       ContextCompat.getColor(context, R.color.mainColor),
                       Color.parseColor("#2BEE8C")).apply {
                       duration = 500
                       repeatCount = ValueAnimator.INFINITE
                       repeatMode = ValueAnimator.REVERSE

                        addUpdateListener { animator ->
                          val color = animator.animatedValue as Int
                           binding.btn.backgroundTintList = ColorStateList.valueOf(color)
                      }
                   }
                  colorAnimation.start()
               }, 4000)
           }
       }

만약 DialogFragment라던지 아니면 api를 사용해서 서버와 통신중인데 무리하게 context에 접근하다가 오류가 날 때는 let을 활용해서 
context가 있을 때만 사용하게 끔 하면 예외처리가 깔끔해진다는 점..

 

 


토스트로 확인해보기

 

Toast.makeText(requireContext(), "오류 확인하쇼", Toast.Length_SHORT).show()

라는 코드를 catch문이나 어딘가에 넣기로 돼 있는데 이게 테스트할 때 삑이 나기 때문에 

context?.let { context -> 
	if (context != null) Toast.makeText(context, "오류 확인하쇼", Toast.Length_SHORT).show()
}

하면 토스트도 컨텍스트가 잘 붙어있을 때만 보여짐 ㅎ

암튼 디버깅 시리즈는 꾸준히 올릴예정.