1. Non-Static Inner Classes
- Kotlin의 내부 클래스는 외부 클래스에 대한 암시적 참조를 보유할 수 있음
Example:
class MyActivity : AppCompatActivity() {
private inner class MyThread : Thread() {
override fun run() {
// Task
}
}
}
- 해결 방법: 내부 클래스를 정적으로 만들거나, 별도의 클래스를 사용하기. 필요한 경우 외부 클래스에 대한 약한 참조를 전달
2. Handlers and Runnables
- 핸들러가 외부 클래스에 대한 참조를 보유하는 경우 메모리 누수가 발생할 수 있음
Example:
class MyActivity : AppCompatActivity() {
private val handler = Handler(Looper.getMainLooper())
private val runnable = Runnable { /* Task */ }
override fun onDestroy() {
super.onDestroy()
handler.removeCallbacks(runnable)
}
}
- 해결 방법:
onDestroy
메서드에서 콜백을 모두 제거
3. Anonymous Listeners
- 리스너가 실수로 Activity나 View에 대한 참조를 보유할 수 있음
Example:
class MyActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
findViewById<Button>(R.id.myButton).setOnClickListener {
// Click action
}
}
}
- 해결방법: onDestroy 메소드에서 리스너를 지우거나 정적 클래스를 사용
4. Static Views or Contexts
- 정적 뷰 또는 컨텍스트 참조는 메모리 누수로 이어질 수 있음
Example:
class MyActivity : AppCompatActivity() {
companion object {
private var staticView: View? = null
}
override fun onCreate(savedInstanceState: Bundle?) {
staticView = findViewById(R.id.myView)
}
}
- 해결 방법: 뷰나 컨텍스트에 대한 정적 참조를 피하고, 필요한 경우 약한 참조를 사용
5. Improper LiveData Observations
- 수명주기를 고려하지 않고 LiveData를 관찰함
Example:
class MyActivity : AppCompatActivity() {
private val viewModel: MyViewModel by viewModels()
override fun onCreate(savedInstanceState: Bundle?) {
viewModel.myLiveData.observe(this, { data ->
/* Update UI */
})
}
}
- 해결 방법:
viewLifecycleOwner
Fragments와 같은 수명 주기 인식 구성 요소를 사용하여 LiveData를 관찰
6. Singleton with Context
- 컨텍스트에 대한 참조를 보유하는 싱글톤은 누출을 일으킬 수 있음
Example:
object MySingleton {
var context: Context? = null
}
- 해결 방법: Activity나 View컨텍스트 대신, 애플리케이션 컨텍스트를 싱글톤에 전달
7. Bitmaps
- 대형 비트맵을 제대로 관리하지 않으면 많은 메모리를 소비할 수 있음
Example:
class MyActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
val bitmap = BitmapFactory.decodeResource(resources, R.drawable.large_image)
// Use bitmap
}
}
- 해결방법: 비트맵을 신중하게 사용하고
recycle()
완료되면 호출. Glide나 Picasso와 같은 이미지 로딩 라이브러리를 사용
8. WebViews
- WebView는 컨텍스트에 대한 참조를 보유할 수 있음
Example:
class MyActivity : AppCompatActivity() {
private lateinit var webView: WebView
override fun onCreate(savedInstanceState: Bundle?) {
webView = findViewById(R.id.myWebView)
// Set up WebView
}
}
- 해결 방법: onDestroy 메소드에서 WebView를 지우고, 가능한 경우 애플리케이션 컨텍스트를 사용
9. Broadcast Receivers
- broadcast receivers등록을 취소하지 않으면 누출이 발생할 수 있음
Example:
class MyActivity : AppCompatActivity() {
private val receiver = MyReceiver()
override fun onStart() {
registerReceiver(receiver, IntentFilter("SOME_ACTION"))
}
override fun onStop() {
unregisterReceiver(receiver)
super.onStop()
}
}
- 해결 방법: 항상 해당 수명 주기 메서드에서 등록을 취소하기
10. Event Listeners in RecyclerView Adapters
- RecyclerView 어댑터의 이벤트 리스너는 Activity 또는 Fragment에 대한 참조를 보유할 수 있음
Example:
class MyAdapter(private val items: List<Item>, private val activity: AppCompatActivity) : RecyclerView.Adapter<MyViewHolder>() {
// Adapter implementation
}
- 해결 방법: 콜백에 인터페이스나 람다 함수를 사용하고, Activity나 Fragment 컨텍스트를 어댑터에 전달하지 않기.
Uploaded by N2T