huzit
___을 입력해주세요
huzit
전체 방문자
  • 분류 전체보기 (137)
    • 안드로이드(Compose) (10)
      • UI (4)
      • 개념 (6)
    • 안드로이드 (50)
      • 기본개념 (6)
      • 응용 (4)
      • Debug (18)
      • Binding (3)
      • RecyclerView (5)
      • Firebase (6)
      • Retrofit (1)
      • Activity & Fragment (4)
    • 코틀린 (22)
    • 코딩테스트 (38)
      • 백준 (10)
      • 프로그래머스 (28)
    • 일상 (6)
    • CS 지식 (4)
    • 라즈베리파이 (7)

블로그 메뉴

  • 홈
  • 태그
  • 글쓰기
  • 관리

공지사항

인기 글

태그

  • 공돌이파파
  • compose
  • recyclerView ClickEvent
  • 프로그래머스
  • Java
  • Kotlin
  • 브레빌 밤비노 플러스
  • IFTTT
  • 코틀린
  • Debug
  • FCM
  • 라즈베리 파이
  • RecyclerView
  • jetpack
  • 공돌카돈
  • gts4mini
  • docker
  • Android
  • Retrofit
  • firebase

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
huzit

___을 입력해주세요

SingleTon Holder로 편하게 SingleTon 쓰기
안드로이드/응용

SingleTon Holder로 편하게 SingleTon 쓰기

2023. 9. 22. 13:17
728x90
class MyViewModel(){

	companion object: SingleTonHolder<MyViewModel>
}

Compose에서 ViewModel로 데이터 전달을 하다 보니 항상 같은 인스턴스를 사용할 필요가 생겼습니다.

코드

1. 싱글톤으로 호출할 클래스의 생성자가 없는 경우

open class SingletonHolder<out A> (creator: () -> A) {
    private var creator: (() -> A)? = creator
    @Volatile
    private var instance: A? = null

    fun getInstance(): A{
        val checkInstance = instance

        if(checkInstance != null)
            return checkInstance

        return synchronized(this){
            val checkInstanceAgain = instance

            if(checkInstanceAgain != null)
                checkInstanceAgain
            else{
                val created = creator!!()
                instance = created
                creator = null
                created
            }
        }
    }
}

2. 싱글톤으로 호출할 클래스의 생성자의 패러미터가 1개인 경우

open class SingletonHolderOneArg<in T, out A>(creator: (T) -> A){
    private var creator:((T) -> A)? = creator
    @Volatile
    private var instance: A? = null

    fun getInstance(t: T): A {
        val checkInstance = instance

        if(checkInstance != null)
            return checkInstance

        return synchronized(this){
            val checkInstanceAgain = instance
            if(checkInstanceAgain != null)
                checkInstanceAgain
            else{
                val created = creator!!(t)
                instance = created
                creator = null
                created
            }
        }
    }
}

3. 같은 타입의 생성자 패러미터가 2개 이상 인경우

open class SingletonHolderTwoArg<in T, out A>(creator: (T, T, ...) -> A){
    private var creator:((T, T, ...) -> A)? = creator
    @Volatile
    private var instance: A? = null

    fun getInstance(t: T, t2: T, ...): A {
        val checkInstance = instance

        if(checkInstance != null)
            return checkInstance

        return synchronized(this){
            val checkInstanceAgain = instance
            if(checkInstanceAgain != null)
                checkInstanceAgain
            else{
                val created = creator!!(t, t2, ...)
                instance = created
                creator = null
                created
            }
        }
    }
}

4. 3번이 다른 타입일 경우

open class SingletonHolderOtherTwoArg<in T, in B, out A>(creator: (T, B) -> A){
    private var creator:((T, B) -> A)? = creator
    @Volatile
    private var instance: A? = null

    fun getInstance(t: T, t2: B): A {
        val checkInstance = instance

        if(checkInstance != null)
            return checkInstance

        return synchronized(this){
            val checkInstanceAgain = instance
            if(checkInstanceAgain != null)
                checkInstanceAgain
            else{
                val created = creator!!(t, t2)
                instance = created
                creator = null
                created
            }
        }
    }
}

코드 설명

open class SingletonHolderOneArg<in T, out A>(creator: (T) -> A){
    private var creator:((T) -> A)? = creator
    @Volatile
    private var instance: A? = null

    fun getInstance(t: T): A {
        val checkInstance = instance

        if(checkInstance != null)
            return checkInstance

        return synchronized(this){
            val checkInstanceAgain = instance
            if(checkInstanceAgain != null)
                checkInstanceAgain
            else{
                val created = creator!!(t)
                instance = created
                creator = null
                created
            }
        }
    }
}

1. in & out

 

제네릭 ( in & out)

타입을 변수처럼 받을 수 있도록 하는 방법 자바와 마찬가지로 코틀린 클래스는 타입 패러미터를 가질 수 있다. class Box(t: T){ val value = t } 일반적으로 제네릭 클래스의 인스턴스를 생성할 때 타

huzit.tistory.com

2.  @Volatile

휘발성이란 의미입니다. 어노테이션이며 메인 메모리에만 적재되어 멀티 스레드 환경에서 CPU 캐시 값이 아닌 메인 메모리 값을 참조하므로 값 불일치 문제를 방지할 수 있습니다.

3. synchronized()

동기 실행 시킨다는 의미입니다. 멀티 스레드 환경에서 이 block의 작업만은 완전히 끝난 이후 다시 다른 작업을 한다라고 볼 수 있습니다.

호출 방법

싱글톤으로 만들고 싶은 클래스의 companion object에 상속시켜 주면 됩니다.

class MyViewModel: ViewModel(){
	companion object: SingletonHolder<MyViewModel>(::MyViewModel)
}

//생성자 패러미터 1개일 경우
class MyViewModel(a: String): ViewModel(){
	companion object: SingletonHolder<String, MyViewModel>(::MyViewModel)
}

in, out 타입에 맞춰서 넣어주면 됩니다. SingletonHolder의 creator은 싱글톤으로 만들려는 클랙스를 ::을 통해 리플렉션 해주면 됩니다.

이렇게 하면 어디에서든지. getInstance() 함수로 호출할 수 있습니다.

MyViewModel.getInstance()

MyViewModel("TEST").getInstance()
728x90
저작자표시 (새창열림)

'안드로이드 > 응용' 카테고리의 다른 글

다국어 지원 (Wear OS)  (0) 2023.11.17
FusedLocationService로 위치 조회  (0) 2023.09.25
ApplicationContext 일반 클래스에서 쓰기  (0) 2023.09.22
    '안드로이드/응용' 카테고리의 다른 글
    • 다국어 지원 (Wear OS)
    • FusedLocationService로 위치 조회
    • ApplicationContext 일반 클래스에서 쓰기
    huzit
    huzit
    simple is best

    티스토리툴바