[안드로이드 공부]/코틀린 11

Kotlin by VS .value collectAsStateWithLifecycle

val groupsUiState by viewModel.groupsUiState.collectAsStateWithLifecycle() val groupsUiState = viewModel.groupsUiState.collectAsStateWithLifecycle().value 두 코드는 Kotlin의 by 키워드를 사용하는 방식과 직접 .value를 호출하는 방식의 차이를 보여줍니다.   val groupsUiState by viewModel.groupsUiState.collectAsStateWithLifecycle() 이 코드는 Kotlin의 위임 프로퍼티(delegated property)를 사용합니다. by 키워드를 사용하면 groupsUiState의 값은 viewModel.groupsUiState..

MutableStateFlow .update VS .value = 차이점

private val _uiState = MutableStateFlow(UiState.Loading)_uiState.update { when (state) {VS_uiState.value = state 두 방법 모두 MutableStateFlow의 값을 업데이트하는 방법이지만, 사용 상황에 따라 적합한 방법이 다르다._uiState.update { }: 이 방법은 현재 MutableStateFlow의 값에 기반하여 새 값을 계산할 때 유용하다. 이 함수는 현재 값을 인자로 받는 람다 함수를 사용하며, 람다 함수의 반환 값이 새로운 값으로 설정됨.  _uiState.value = state: 이 방법은 새 값이 현재 값에 의존하지 않을 때 사용한다. 이 방법은 단순히 MutableStateFlow의 ..

listOf()와 emptyList() 차이

listOf()와 emptyList() 모두 코틀린에서 빈 리스트를 생성하는 함수. listOf()는 가변 인자를 받아서 리스트를 생성하는 함수다. 인자 없이 호출하면 빈 리스트를 반환한다.  emptyList()는 항상 빈 리스트를 생성하는 함수로 listOf()와 emptyList()는 인자 없이 호출할 경우 동일한 결과, 즉 빈 리스트를 반환함. 그러나 이 두 함수 사이에는 성능 차이가 있다. emptyList()는 항상 같은 인스턴스를 반환하기 때문에 새로운 객체를 생성하지 않음. 반면에 listOf()는 호출할 때마다 새로운 리스트를 생성함.  따라서 빈 리스트를 생성할 때는 emptyList()를 사용하는 것이 더 효율적.

Inheritance from an interface with '@JvmDefault' members is only allowed with -Xjvm-default option

Inheritance from an interface with '@JvmDefault' members is only allowed with -Xjvm-default option viewModel 에 param을 추가하였더니 viewModel Factory가 필요하고, 추가 하니 위와 같은 에러가 나왔다~ 버전 충돌 문제인데~ build.gradle.app 에 kotlinOptions { jvmTarget = '1.8' freeCompilerArgs += [ '-Xjvm-default=enable' ] } 또는 tasks.withType(KotlinCompile).configureEach { kotlinOptions { freeCompilerArgs += [ "-Xjvm-default=all", ] } }..

android worker ClassNotFoundException

Room 에서 DB 가 만들어지고, 초기화를 할 때 OnCreate() 에서 아래와 같이 워커를 불러서 작업을 하는데, val request = OnTimeWorkRequestBuilder().build() WorkManager.getInstance(context).enqueue(request) enqueue 에 작업을 넣으려고 하면 아래와 같이 요상한 에러가 난다. 아무리 인터넷을 뒤져도 답이 없다. E/AndroidRuntime: FATAL EXCEPTION: arch_disk_io_0 java.lang.NoClassDefFoundError: Failed resolution of: Landroidx/work/impl/utils/futures/AbstractFuture; Caused by: java.l..

smart cast to is impossible because is a mutable property that could have been changed by this time

변경될 수 있는(mutable/var) 타입을 캐스팅 할 경우 문제가 생긴다. 이 경우에는 val 불변 타입으로 새로운 변수에 할당 한 뒤에 캐스팅을 해야 한다. private val plantDetailViewModel: PlantDetailViewModel by viewModels { InjectorUtils.providePlantDetailViewModelFactory(requireActivity(), args.plantId) } val binding = DataBindingUtil.inflate( inflater, R.layout.fragment_plant_detail, container, false ).apply { viewModel = plantDetailViewModel //error bea..

[MVVM] LiveData와 ViewModel Observer로 연결

Repository의 Data가 변경 되었을 때 UI에 알리기 위해서는 ViewModel이 관찰을 하고 있어야 한다. UI(V)는 보통 onCreate()에서 VM을 생성하고, VM은 Repository를 생성한 뒤 M과 Dao를 통해 연결 되는데, 이 Dao를 LiveData로 구성하면 ViewModel이 지켜 볼 수(obsever) 있게 된다. 연결(MVVM) onCreate/onCreateView 실행이 되면서 viewModel 생성 작업과 이후 연결 작업이 실행 된다. Fragment.kt private val plantDetailViewModel: PlantDetailViewModel by viewModels { InjectorUtils.providePlantDetailViewModelFacto..

코틀린 생성자와 위임

주 생성자와 부 생성자 2가지로 나뉘며, 주 생성자는 클래스 선언 시 가시성 접근자(없으면 클래스 명) 뒤에 선언한다. class Car private constructor(_name: String) 자바는 부 생성자 처럼 클래스 내부에 선언 한다 private class Car { class(String name) } 부 생성자는 클래스 내부에서 파라미터를 달리하여 만든다. class Car private constructor(_name: String) { constructor(value: Int)} 클래스 생성 시 생성자를 정의하지 않으면 컴파일러는 인자가 없는 디폴트 생성자를 만든다 주 생성자 class Car constructor(_name: String){ val name : String ini..

추상클래스(abstract)와 인터페이스(interface)

차이점 추상 클래스는 상속과 필수구현을 위해 인터페이스는 필수구현을 위해 추상 클래스 클래스 내에 추상 메서드가 하나 이상 포함 되거나, abstract 로 정의 된 경우 추상 메서드가 하나라도 있으면 class 앞에 abstract 를 붙여야 함 추상 메서드는 구현 되지 않으며 상속받은 클래스에서만 구현되어야 한다. abstract 에는 final 을 붙일 수 없다. 이미 open 이다 생성자, 전역 변수도 선언 할 수 있고, 메서드 내용이 있을 수도 있다. 다중 상속 안됨 추상 클래스는 직접 생성될 수 없으며, 다른 클래스를 통해 생성되어야 한다. 직접 Car() 로 생성하면 아래와 같은 에러가 나타난다. Cannot create an instance of an abstract class abstra..