목록분류 전체보기 (140)
시배's Android
아이템19. knowledge를 반복하여 사용하지 말라 knowledge는 넓은 의미로 의도적인 정보를 뜻합니다. 프로젝트를 진행할 때 정의한 모든 것이 knowledge입니다. 알고리즘의 작동 방식, UI의 형태, 우리가 원하는 결과 등이 모두 의도적인 정보이며, knowledge입니다. 로직 : 프로그램이 어떠한 식으로 동작하는지와 프로그램이 어떻게 보이는지 공통 알고리즘 : 원하는 동작을 하기 위한 알고리즘 둘의 가장 큰 차이점은 시간에 따른 변화입니다. 비즈니스 로직은 시간이 지나면서 계속해서 변하지만 콩통 알고리즘은 한 번 정의된 이후에는 크게 변하지 않습니다. knowledge도 계속해서 변한다. 회사가 사용자의 요구 또는 습관을 더 많이 알게 되었다. 디자인 표준이 변화했다. 플랫폼, 라이브..
코루틴은 가장 먼저 완료되는 코루틴의 결과를 기다리는 select 함수를 제공합니다. 또한 여러 개의 채널 중 버퍼에 남은 공간이 있는 채널을 먼저 확인하여 데이터를 보내거나, 이용 가능한 원소가 있는 채널로부터 데이터를 받을 수 있는지 여부도 확인할 수 있습니다. 코루틴 사이에 경합을 일으키거나, 여러 개의 데이터 소스로부터 나오는 결과값을 합칠 수도 있습니다. 지연되는 값 선택하기 여러 개의 소스에 데이터를 요청한 뒤, 가장 빠른 응답만 얻는 경우를 생각해봅시다. 요청을 여러 개의 비동기 프로세스로 시작한 뒤, select 함수를 표현식으로 사용하고 표현식 내부에서 값을 기다리는 것입니다. select 내부에서는 셀렉트 표현식에서 나올 수 있는 결괏값을 명시하는 Deferred 값의 onAwait 함..
채널은 송신자와 수신자의 수에 제한이 없으며, 채널을 통해 전송된 모든 값은 단 한 번만 받을 수 있습니다. Channel은 두 개의 서로 다른 인터페이스를 구현한 하나의 인터페이스입니다. SendChannel은 원소를 보내거나 채널을 닫는 용도로 사용됩니다. ReceiveChannel은 원소를 받을 때 사용됩니다. 채널의 진입점을 제한하기 위해 ReceiveChannel이나 SendChannel 중 하나만 노출시키는 것도 가능합니다. receive를 호출했는데 채널에 원소가 없다면 코루틴은 원소가 들어올 때 까지 중단됩니다. 반면 send는 채널의 용량이 다 찼을 때 중단됩니다. 용량이 제한적인 채널에서만 trySend tryReceive를 사용해야 합니다. produce 함수는 빌도로 시작된 코루틴이..
아이템11. 가독성을 목표로 설계하라 // 구현 A if (person != null && person.isAdult) { view.showPerson(person) } else { view.showError() } // 구현 B person?.takeIf { it.isAdult } ?.let(view::showPerson) ?. view.showError() 가독성이란 코드를 읽고 얼마나 빠르게 이해할 수 있는지를 의미합니다. 구현 A는 수정하기 쉽습니다. 구현 A는 디버깅도 더 간단합니다. 기본적으로 인지부하를 줄이는 방향으로 코드를 작성해야한다. 극단적이지 않기 let으로 인해서 예상하지 못한 결과가 나올 수 있다. (view.showPerson 에서 nullable을 리턴하는 경우) let은 절대..
TestCoroutineScheduler와 StandardTestDispatcher TestCoroutineScheduler는 delay를 가상 시간 동안 실행하여 실제 시간이 흘러간 상황과 동일하게 작동하기 때문에 정해진 시간만큼 기다리지 않도록 변경할 수 있습니다. 코루틴에서 TestCoroutineScheduler를 사용하려면, 이를 지원하는 디스패처를 사용해야 합니다. 일반적으로 StandardTestDispatcher를 사용합니다. 테스트 디스패처로 시작된 코루틴은 가상 시간만큼 진행되기 전까지 실행되지 않습니다. StandardTestDispatcher는 TestCoroutineScheduler를 만들기 때문에 명시적으로 만들지 않아도 됩니다. StandardTestDispatcher는 직접 ..
동기화 블로킹 자바에서 사용되는 전통적인 도구인 synchronized 블록이나 동기화된 컬렉션을 사용해 해결할 수 있습니다. 가장 큰 문제점은 synchronized 블록 내부에서 중단 함수를 사용할 수 없다는 것입니다. synchronized 블록에서 코루틴이 자기 차례를 기다릴 때 스레드를 블로킹한다는 것입니다. 원자성 자바는 다양한 원자값을 가지고 있습니다. 원자값을 활용한 연산은 빠르며 스레드 안전을 보장합니다. 원자성은 하나의 primitive 변수 또는 하나의 reference의 안전을 보장하기 위해 사용되지만, 좀 더 복잡한 경우에는 다른 방법을 사용해야 합니다. 싱글스레드로 제한된 디스패처 싱글스레드 디스패처를 사용하는 것이 공유 상태와 관련된 대부분의 문제를 해결하는 가장 쉬운 방법입니..
![](http://i1.daumcdn.net/thumb/C150x150/?fname=https://blog.kakaocdn.net/dn/bpuInQ/btsEFQRT86X/PIl6hKdKPSal6sQfBWV2YK/img.png)
위 사진을 보면 TiTi 프로젝트에서 TimeTable의 격자가 제대로 그려지지 않는 상황이 발생하고 있습니다. Compose의 Preview에서는 잘 나오지만 실제 runtime에서는 위와 같이 이슈가 발생하고 있습니다. fun DrawScope.drawGrid() { val itemWidth = size.width / 7 val itemHeight = size.height / 24 var startX = 0f var startY = 0f repeat(7 * 24) { idx -> drawRect( color = Color(0x80626262), topLeft = Offset( x = startX, y = startY, ), size = Size(itemWidth, itemHeight), style =..
![](http://i1.daumcdn.net/thumb/C150x150/?fname=https://blog.kakaocdn.net/dn/cmkwKG/btsEydMNJmu/EI3tWKKiFbwBh3ndQVWoPK/img.png)
TdsTimeTable은 TiTI 프로젝트에서 사용되는 커스텀한 컴포넌트입니다. 이 컴포넌트는 사용자가 진행한 task에 대한 시간을 한눈에 파악할 수 있도록 도와주며, 각 시간대별로 진행한 task를 시각적으로 표현합니다. Canvas( modifier = modifier .drawWithContent { drawContent() drawGrid() }, ) { fun DrawScope.drawGrid() { val itemWidth = size.width / 7 val itemHeight = size.height / 24 var startX = 0f var startY = 0f repeat(7 * 24) { idx -> drawRect( color = Color(0x80626262), topLeft ..