전체 글 (15) 썸네일형 리스트형 [Day 3] lateinit과 by lazy는 내부적으로 어떻게 동작할까? Kotlin은 기본적으로 프로퍼티를 선언함과 동시에 초기화하도록 강제한다(Null Safety). 하지만 안드로이드 개발을 하다보면 Activity가 onCreate()되기 전 까지는 알 수 없는 값이나, 당장 쓰지 않는데 미리 생성하기에는 무거운 객체들이 존재한다. 이럴 경우 주로 사용하게 되는 키워드가 lateinit 과 by lazy 이다. 둘 다 초기화를 미루는 기능인데, 내부적으로 어떻게 다르게 동작할까?1. 한 줄 요약 lateinit 은 컴파일 타임에 null로 초기화해두고 접근 시마다 null 체크를 수행하는 가변(var) property 에약어이며, by lazy 는 property의 getter를 Lazy 위임 객체에 연결하여 최초 호출 시점에 단 한 번만 람다를 실행하고 그 결과.. [Day 2] Kotlin의 Primitive Type은 어떻게 동작할까? Java로 개발할 때는 int, boolean, double 등의 원시 타입과 Integer, Boolean, Double 등의 참조 타입을 명확하게 구분해서 작성한다.하지만 Kotlin에서는 모든 자료형을 Int, Boolean처럼 대문자로 시작하는 클래스 형태로 선언하고, 심지어는 10.toString() 처럼 숫자에 직접 메서드를 호출하기까지 한다. 과연 이 둘의 차이는 뭐고, 어떻게 동작하는지 알아보고자 한다.1. 한 줄 요약Kotlin은 코드 작성 시에는 원시 타입과 참조 타입을 구분하지 않고, 하나의 타입( Int 등)으로 다루지만, 컴파일 시점에 가능한 모든 경우 Java의 원시 타입( int )으로 자동 변환하여 성능을 최적화한다. 단 Nullable 타입( Int? )이나 제네릭( L.. [Day 1] Kotlin에서 val은 상수인가? 코틀린으로 개발할 때 가장 먼저 배우는 것은 var vs val 이 아닐까 싶다. 모두 알다싶이 var 은 새 값을 할당할 수 있지만, val 은 재할당이 불가능하다. 특히 코틀린으로 개발할 때 "가변 변수인 var 대신 불변 변수인 val 을 사용하라"는 규칙을 많이 접하게 되는데, 그렇다면 "Kotlin의 val은 불변(Immutable)을 보장하나요?"라는 질문을 받으면 어떻게 답할 수 있을까?1. 한 줄 요약val은 참조의 재할당만 막는 읽기 전용(read-only) 프로퍼티일 뿐, 커스텀 getter나 가변 객체 참조를 통해 호출 시마다 다른 값을 반환할 수 있으므로 불변(immutable)을 보장하지 않는다. 진짜 컴파일 타임 상수를 만드려면 const val을 사용해야한다.2... [Day 0] 100일 동안 안드로이드 파보기 100일 동안 안드로이드 파보기?코드를 작성할 때 AI를 사용하는 것이 일상이 되었고, 심지어는 요구사항을 입력조차 할 필요 없이 링크만 복사-붙여넣기해도 그럴듯하게 동작하는 코드가 뚝딱 나온다. 당장의 기능을 구현하고 티켓을 쳐내는 속도는 확실히 빨라졌지만, 이대로라면 나를 "개발자"라고 부를 수 있을까? 라는 의문이 든다.특히 최근 두어군데의 기술 면접을 진행했는데 조금만 근원적인 질문이 나와도 쉽게 답이 나오지 않았다. AI로 동작하는 코드는 만들 수 있어도, 그걸 알고 이해하지는 못한 것이다.이런 상황을 타파하기 위해 100개의 안드로이드 기술 블로그 글 작성하기를 시작하려고 한다. Kotlin 코어적인 글로 시작해서 아키텍처, Compose, 성능 최적화까지 이 곳에서 Android를 내 지식으.. SavedInstanceState와 ViewModel SavedInstanceState 앱을 만들면서 늘 지나치던 아이가 있다…. onCreate에서 인자로 들어오는 savedInstanceState인데, Bundle 자료형으로 들어온다고 한다. 보통 화면을 회전할 때 사용한다고 개념적으로 알고만 있는데 이번에 직접 사용해보려고 한다. class MainActivity : AppCompatActivity() { private val binding: ActivityMainBinding by lazy { DataBindingUtil.setContentView(this, R.layout.activity_main) } var count = 0 override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(.. lifecycleOwner와 viewLifecycleOwner의 차이 Fragment에서 LiveData를 observe할 때 LifecycleOwner로 Fragment 자체를 넣게 되면 viewLifecycleOwner를 사용하라는 에러가 표시된다. 처음엔 Fragment는 lifecycleOwner가 따로 없어서 viewLifecycleOwner를 사용해야하는구나 하고 넘어갔다. 당연한 건 없었다…. Fragment는 분명 LifecycleOwner를 상속받고 있기 때문에 LiveData의 observe에서도 사용이 가능한 게 정상이다. 심지어 DataBinding의 lifecycleOwner에는 정상적으로 잘 들어가지만 observe에서 사용할 때만 빨간줄로 에러가 표시된다. 그 이유는 Fragment의 lifecycleOwner와 viewLifecycleOwner.. RoomDB에서 LiveData 사용 예전 포스팅에서 Realm이 RoomDB보다 사용이 간편해 Realm을 사용한다고 했는데, 그 중 가장 크게 작용했던 RoomDB의 단점이 Main Thread에서는 사용이 불가능하다는 점이었다. 이전 포스트 👉 Room DB 사용하기 그런데 회사 프로젝트 진행을 하던 중 LiveData를 사용하면 메인 스레드에서도 데이터를 읽어올 수 있다는 글을 보게 되었다. LiveData 자체가 비동기적으로 동작하기 때문에 Main Thread에서도 에러가 발생하지 않는다는 것이 핵심이었다. 이를 토대로 위 포스트의 코드를 리팩토링 해본다면 @Dao interface RecipeDao { ... @Query("SELECT * FROM recipe") fun getAll(): LiveData ... } 위처럼 SEL.. Android Custom View 만들기 해당 뷰 하단의 버튼들을 보면 모두 같은 레이아웃에 아이콘과 텍스트만 다르다는 것을 볼 수 있다. 이럴 때는 커스텀뷰를 사용해 뷰를 정의하면 버튼마다 레이아웃과 뷰를 만들어줄 필요 없이 커스텀 뷰 하나만 만들어주면 되기 때문에 상당히 편리하다. 커스텀뷰를 만드는 것은 세 단계를 거친다. 뷰 구현 속성 정의 뷰 클래스 구현 1. 뷰 구현 우선 커스텀뷰의 xml 파일을 만들어준다. 데이터바인딩을 사용하기 위해 layout 태그로 감싸는 것도 잊지 말자. 대략 원하는 형태의 뷰가 만들어졌다. 2. 속성 정의 이제 해당 뷰에서 사용하는 속성을 정의해야한다. 해당 뷰에서는 이모지, 타이틀, 카운트가 다르므로 세 개의 속성을 받을 것이다. values 폴더 내에 attrs.xml 파일을 만들고 속성과 자료형을 입력.. 이전 1 2 다음