분류 전체보기

    Unable to add window -- token null is not valid; is your activity running?

    Unable to add window -- token null is not valid; is your activity running?

    원인 Dialog에 context를 넘겨 줄 때 ApplicationContext를 넘겨주면 발생하는 에러 val dialog = BasicDialog(applicationContext) .setTitle("KeepMe에 업데이트가 필요합니다") .setMessage("이 앱을 사용하려면 최신 버전을 다운로드하세요.") .setPositiveButton("업데이트") { startActivity( Intent( Intent.ACTION_VIEW, Uri.parse(appUpdateURL) ) ) } 해결 현재 액티비티의 context를 넣어주거나 fragment일 경우 requireContext()로 context를 가져와 넘겨주면 된다 val dialog = BasicDialog(this) .setTi..

    [Text] Text 패러미터 정리

    [Text] Text 패러미터 정리

    컴포즈 프로젝트를 생성하면 가장 먼저 만나는 컴포저블인 Text입니다. 기존 안드로이드의 TextView는 수많은 위젯의 부모였지만 컴포즈에선 그냥 단일 함수입니다. 전체 코드 @Composable fun Text( text: String, modifier: Modifier = Modifier, color: Color = Color.Unspecified, fontSize: TextUnit = TextUnit.Unspecified, fontStyle: FontStyle? = null, fontWeight: FontWeight? = null, fontFamily: FontFamily? = null, letterSpacing: TextUnit = TextUnit.Unspecified, textDecoratio..

    NetworkOnMainThreadException

    NetworkOnMainThreadException

    원인 안드로이드에서 네트워크 작업은 메인 스레드가 아닌 작업스레드에서 해야함 해결 kotlin이면 CoroutinScope(Dispacher.Default).launch{} 로 감싸면 해결 자바면 쓰레드 하나 만들어주면 된다.

    Preview

    Preview

    컴포즈를 쓰면 가장 먼저 알아야 할 기능인 Preview입니다. Preview를 통해 레이아웃을 볼 수 있으며 Interactive 기능을 통해 간단한 기능 테스트를 해볼 수 있습니다. xml vs Compose Preview 기존 xml과 다르게 compose는 @Preview 어노테이션을 통해 내가 작성한 레이아웃을 볼 수 있습니다. 기능 말 그대로 작성한 레이아웃을 보여주는 기능을 합니다. 예를 들어 Greeting 컴포저블에 Button을 하나 더 추가하고 실제 휴대폰처럼 보고 싶다면 버튼 컴포저블과 Preview의 showSystemUi를 true 주면 됩니다. @Composable fun Greeting(name: String, modifier: Modifier = Modifier) { Col..

    [Retrofit 통신 실패]java.lang.IllegalStateException: Expected a string but was BEGIN_OBJECT at line 1 column 2 path $

    [Retrofit 통신 실패]java.lang.IllegalStateException: Expected a string but was BEGIN_OBJECT at line 1 column 2 path $

    원인 우리가 Response로 받을 거라 생각했던 타입과 실제 들어온 Response의 타입이 달랐을 때 발생하는 오류 해결 Response의 타입에 맞게 데이터 클래스를 선언해 주거나 오브젝트를 String으로 변환시켜 주는 ScalarsConverterFactory 라이브러리를 사용하거나 둘 중 하나를 택하면 된다. 2번을 선택할 경우 방법은 다음과 같다. 의존성 추가 implementation 'com.squareup.retrofit2:converter-scalars:2.9.0' retrofit 선언부에 추가 .addConverterFactory(ScalarsConverterFactory.create()) val rt = retrofit2 .Retrofit .Builder() .baseUrl(bas..

    Key 1 was already used. If you are using LazyColumn/Row please make sure you provide a unique key for each item.

    Key 1 was already used. If you are using LazyColumn/Row please make sure you provide a unique key for each item.

    원인 LazyColumn 또는 LazyRow를 쓸 때 각 항목에 고유한 위치값을 안 썼기 때문 LazyColumn에 item을 추가하는 기능을 만들었을 때 발생할 수 있다. 기본 레이아웃일 경우 자체적으로 처리되지만 커스텀일 경우 items의 key 패러미터에 고유한 key값을 넘겨줘야 한다. itemsIndexed( items = cl, key = { index: Int, item: CheckListInfo -> item.hashCode() } ) 나의 경우 key값으로 item의 해시 값을 넣어줬지만 내용이 같으면 해시값도 같으므로 위와 같은 에러가 발생했다. 해결 간단하다. 안겹치는 고유한 키 값을 주면 된다. itemsIndexed( items = cl, key = { index: Int, _: ..

    Expected a boolean but was BEGIN_OBJECT at line 1 column 85 path $[0].visibility

    Expected a boolean but was BEGIN_OBJECT at line 1 column 85 path $[0].visibility

    원인 엔티티에 들어가는 데이터 클래스 프로퍼티의 타입을 바꿈 해결 원래 들어가있던 데이터와 바뀐 프로퍼티의 타입이 충돌을 일으키는 것 이므로 앱 데이터 삭제 후 재 시작