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 |