일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- 큐 자바 코드
- 스택 자바 코드
- Rxjava Observable
- jvm 작동 원리
- 자바 다형성
- rxjava cold observable
- 멤버변수
- rxjava disposable
- 안드로이드 유닛 테스트
- ANR이란
- 클래스
- ar vr 차이
- 2022 플러터 설치
- 안드로이드 유닛 테스트 예시
- 안드로이드 레트로핏 crud
- rxjava hot observable
- android retrofit login
- android ar 개발
- 안드로이드 os 구조
- 안드로이드 라이선스 종류
- 서비스 vs 쓰레드
- 플러터 설치 2022
- 스택 큐 차이
- 2022 플러터 안드로이드 스튜디오
- 안드로이드 라이선스
- 안드로이드 레트로핏 사용법
- jvm이란
- 안드로이드 유닛테스트란
- 서비스 쓰레드 차이
- 객체
- Today
- Total
나만을 위한 블로그
[Kotlin] use 확장 함수 알아보기 본문
예전에 이펙티브 코틀린을 읽으면서 use를 써서 리소스를 닫으라는 내용을 봤었다.
https://onlyfor-me-blog.tistory.com/489
요약하면 Input/OutputStream, Scanner 등의 요소들은 더 이상 사용하지 않는다면 close()를 통해 리소스를 거둬들이는 게 좋다는 내용이다.
그러나 use라는 게 무엇이길래 사용하라고 한 것일지 궁금했고, 마침 동영상을 서버로 업로드하는 로직을 구현하는 과정에서 InputStream을 사용하게 됐는데 이 기회에 알아보고자 포스팅한다.
코틀린 공식문서에서 말하는 use와 구현 상세는 아래와 같다.
https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.io/use.html
이 리소스에서 지정된 블록 함수를 실행한 다음 예외 발생 여부에 상관없이 올바르게 종료한다
구현 코드는 안드로이드 스튜디오에서 확인한 내용을 가져왔다. 추가로 매개변수와 리턴값에 대해서도 설명하고 있어서 이것도 가져왔다.
Params : block - 이 Closeable 자원을 처리하는 함수
Returns : 이 리소스에서 호출된 블록 함수의 결과
@InlineOnly
@RequireKotlin("1.2", versionKind = RequireKotlinVersionKind.COMPILER_VERSION, message = "Requires newer compiler version to be inlined correctly.")
public inline fun <T : Closeable?, R> T.use(block: (T) -> R): R {
contract {
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
}
var exception: Throwable? = null
try {
return block(this)
} catch (e: Throwable) {
exception = e
throw e
} finally {
when {
apiVersionIsAtLeast(1, 1, 0) -> this.closeFinally(exception)
this == null -> {}
exception == null -> close()
else ->
try {
close()
} catch (closeException: Throwable) {
// cause.addSuppressed(closeException) // ignored here
}
}
}
}
확인해 보면 알겠지만 use 함수는 Closeable이란 파일 안에 위치하고 있다. 이건 또 뭔가?
https://developer.android.com/reference/kotlin/java/io/Closeable
닫을 수 있는 데이터의 소스 또는 대상이다. 객체가 갖고 있는 리소스(열린 파일 등)를 해제하기 위해 close 메서드가 호출된다
close() : 이 스트림을 닫고 연결된 모든 시스템 리소스를 해제한다
Closeable은 WebSocketReader, Http2Connection, FileIntputStream 등의 클래스가 구현하고 있는 인터페이스다. 이 인터페이스의 구현체를 사용한다면 위에서 말했듯 사용 후 close()를 호출하는 코드가 필요하다.
그러나 객체마다 close()를 호출해야 하고 혹시 모를 예외를 막기 위해 try-catch로 감싸서 처리해야 하는데, 그렇게 되면 코드 가독성도 떨어지고 쓸데없이 긴 줄을 차지하게 된다. 이 때 use를 사용하면 close() 호출 처리를 생략하면서 깔끔한 코드를 작성할 수 있다.
아래는 간단한 예시다.
fun main() {
val url = "https://www.naver.com/"
val destination = File("downloaded_data.txt")
downloadFromWeb(url, destination)
println("Data downloaded to ${destination.absolutePath}")
}
fun downloadFromWeb(url: String, destination: File) = URL(url).openStream().use { input ->
destination.outputStream().use { output ->
input.copyTo(output)
}
}
이 코드를 실행하면 네이버 메인 화면을 구성하는 html 태그들을 가져와서 txt 파일에 저장한다. 실행하면 해당 파일이 저장된 경로가 콘솔에 표시될 것이다.
내 경우 이 프로젝트의 루트 폴더에 downloaded_data.txt 파일이 저장됐다. 직접 실행해서 확인해 보자.
downloadFromWeb()이 주목할 함수다. 이 함수의 첫 부분인 URL(url).openStream() 호출을 통해 InputStream을 만들고, destination.outputStream()을 통해 다운받은 데이터를 파일에 쓸 때 사용할 OutputStream을 만든다.
이를 통해 각 스트림마다 use 확장함수를 사용하기 때문에 close()를 2번 호출할 필요 없이 아주 간단하게 스트림들을 닫고 프로그램을 종료할 수 있다.
안드로이드에서도 이미지, 동영상을 다룰 때 InputStream과 OutputStream을 다뤄야 할 때가 종종 있다. 이 때 try-catch 대신 use 확장함수를 써서 처리해 보는 것도 좋을 것이다.
'개인 공부 > Kotlin' 카테고리의 다른 글
[Kotlin] 에러 처리 Best Practices (0) | 2023.09.08 |
---|---|
[Kotlin] 코루틴의 취소와 suspendCancellableCoroutine (0) | 2023.08.06 |
[Kotlin] enum 사용 시 values() 대신 entries를 써라? (0) | 2023.07.19 |
[Kotlin] Sealed Class와 Sealed Interface란? (0) | 2023.06.06 |
[Kotlin] 세마포어, 뮤텍스 구현 예제 (0) | 2023.04.04 |