목록전체 글 (152)
시배's Android
21장 플로우 만들기 원시값을 가지는 플로우 flowOf를 활용해 간단하게 플로우를 만들 수 있다. flowOf(1, 2, 3, 4,5 ).colect { // TODO } 값이 없는 플로우면 emptyFlow의 형태로 제공 컨버터 asFlow를 활용해 다음과 같은 타입을 플로우로 바꿀 수 있다. Iterable Iterator Sequence Mono Flux List 등등 함수를 플로우로 선언하기 함수가 플로우를 반환하도록 할 수 있다. fun someFunction(): Flow = flow { // Do Something emit(2) } 플로우와 리액티브 스트림 Flux, Mono또한 라이브러리에서 플로우의 변환을 제공한다. kotlinx-coroutines-reactor라이브러리를 활용하라 채..
20장 플로우의 실제 구현 플로우의 내부구현에 대해 알아보자. Flow 이해하기 간단한 람다식 @Test fun main() = runTest { val f: () -> Unit = { println("A") println("B") println("C") } f() } // 출력 겨로가 A B C 플로우는 위의 람다식과 별반 다를것이 없다. 아래는 실제 플로우의 내부 구현을 간단하게 구현해본 것이다. @Test fun main() = runTest { val f: suspend ((String) -> Unit) -> Unit = { emit -> emit("A") emit("B") emit("C") } f { println(it) } f { println(it) } } // 출력 결과 A B C A B ..
TiTi Side Project | Composable 함수를 Bitmap으로 변환하기 Timer TiTi 프로젝트에서는 Card를 이미지로 변환하여 갤러리에 저장하거나 인스타그램에 공유하는 기능을 추가하려고 합니다. 이를 위해서는 Composable 함수로 구현된 View를 Bitmap으로 변환하는 로직 si8ae.tistory.com 갤러리 저장 먼저, 비트맵 객체를 PNG 포맷의 이미지 파일로 저장하는 과정을 살펴봅시다. 이를 위해 저는 먼저 저장할 파일의 위치와 이름을 정의해야 합니다. 여기서는 Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES)를 사용하여 공용 사진 디렉토리에 파일을 저장하고, 파일 이름은 "..
아이템49. 하나 이상의 처리 단계를 가진 경우에는 시퀀스를 사용하라 sequence 는 지연(lazy) 처리 된다. 따라서 시퀀스 처리 함수들을 사용하면, 데코레이터 패턴으로 꾸며진 새로운 시퀀스가 리턴된다. 시퀀스 처리 함수는 최정 연산이 이루어지기 전까지는 각 단계에서 연산이 일어나지 않는다. Iterable 은 처리 함수를 사용할 때마다 연산이 이루어져 List 가 만들어진다. 컬렉션 처리 연산은 호출할 때 연산이 이루어진다. 시퀀스의 지연 처리 장점 자연스러운 처리 순서를 유지 최소한만 연산 무한 시퀀스 형태로 사용 각각의 단계에서 컬렉션을 만들어 내지 않는다. 시퀀스가 빠르지 않은 경우 컬렉션 전체를 기반으로 처리해야 하는 연산은 시퀀스를 사용해도 빨라지지 않는다. sorted 는 Sequen..
아이템45. 불필요한 객체 생성을 피하라 Int 와 같은 기본형을 사용하면, 일반적으로 기본 자료형 int 로 컴파일 된다. 하지만 nullable 로 만들거나, 타입 아규먼트로 사용할 경우에는 Integer 로 컴파일 된다. 기본 자료형은 null 일 수 없고, 타입 아규먼트로도 사용할 수 없기 때문이다. 객체 생성 비용은 항상 클까? 현대 64비트 JDK 에서 객체는 8바이트의 배수만큼 공간을 차지한다. 앞부분 12바이트는 헤더로서 반드시 있어야 하므로, 최소 크기는 16바이트이다. 추가로 객체에 대한 레퍼런스도 공간을 차지한다. 일반적으로 레퍼런스는 -Xmx32G 까지는 32/64비트 플랫폼 모두 4바이트다. 64비트 플랫폼에서는 32G(-Xmx32G)부터는 8바이트이다. 캐시를 활용하는 팩토리 함..

Timer TiTi 프로젝트에서는 Card를 이미지로 변환하여 갤러리에 저장하거나 인스타그램에 공유하는 기능을 추가하려고 합니다. 이를 위해서는 Composable 함수로 구현된 View를 Bitmap으로 변환하는 로직이 필요합니다. fun Modifier.createCaptureImageModifier(picture: Picture): Modifier = this.drawWithCache { val width = this.size.width.toInt() val height = this.size.height.toInt() onDrawWithContent { val pictureCanvas = Canvas( picture.beginRecording( width, height, ), ) draw(this,..
36. 상속보다는 컴포지션을 사용하라 상속은 관계가 명확하지 않을 때 사용하면, 여러 가지 문제가 발생할 수 있습니다. (‘is-a’ 관계에서 사용) class ProfilerLoader { fun load() { // 프로그래스 바를 보여 줌 // 프로파일을 읽어 들임 // 프로그레스 바를 숨김 } } class ImageLoader { fun load() { // 프로그래스 바를 보여 줌 // 이미지를 읽어 들임 // 프로그레스 바를 숨김 } } 상속을 이용하면 위의 코드를 아래와 같이 시용할 수 있습니다. abstract class LoaderWithProgress { fun load() { // 프로그래스 바를 보여 줌 innerLoad() // 프로그래스 바를 숨김 } abstract fun i..
아이템 33. 생성자 대신 팩토리 함수를 사용하라 클라이언트가 클래스의 인스턴스를 만들게 하는 가장 일반적인 방법은 기본 생성자(Primary constructor)를 사용하는 방법이다. class MyLinkedList{ val head : T val tail : MyLinkedList? } val list = MyLinkedList(1, MyLinkedList(2, null)) 하지만 생성자가 객체를 만들수 있는 유일한 방법은 아니다. 헬퍼 클래스를 생각해보자. fun myLinkedListOf( ): MyLinkedList? { if(elements.isEmpty()) return null val head = elements.first() val elementsTail = elements. copy..