Android 앱 개발 중 Bitmap 리소스 관리에서 자주 마주치는 문제입니다:
try {
val processedBitmap = processImage(originalBitmap)
// 이미지 처리 로직
saveToFile(processedBitmap)
} catch (e: Exception) {
Log.e("TAG", "Error processing image", e)
} finally {
originalBitmap.recycle()
processedBitmap.recycle() // null일 수도 있어서 위험!
}
문제점:
.use 확장 함수.use 함수Kotlin은 Closeable 인터페이스를 구현한 클래스에 .use 확장 함수를 제공합니다:
FileInputStream("file.txt").use { input ->
input.read()
} // 자동으로 close() 호출
하지만 Bitmap은 Closeable을 구현하지 않아서 직접 사용할 수 없습니다.
inline fun <T> Bitmap.use(block: (Bitmap) -> T): T {
return try {
block(this)
} finally {
if (!this.isRecycled) {
this.recycle()
}
}
}
fun processAndSaveImage(inputPath: String, outputPath: String) {
var original: Bitmap? = null
var processed: Bitmap? = null
try {
original = BitmapFactory.decodeFile(inputPath)
processed = applyFilter(original)
saveBitmap(processed, outputPath)
} catch (e: Exception) {
Log.e("ImageProcessor", "Failed to process image", e)
} finally {
original?.recycle()
processed?.recycle()
}
}
.use 확장 함수 활용fun processAndSaveImage(inputPath: String, outputPath: String) {
BitmapFactory.decodeFile(inputPath).use { original ->
applyFilter(original).use { processed ->
saveBitmap(processed, outputPath)
}
}
}
fun mergeImages(path1: String, path2: String): Bitmap {
return BitmapFactory.decodeFile(path1).use { bitmap1 ->
BitmapFactory.decodeFile(path2).use { bitmap2 ->
mergeBitmaps(bitmap1, bitmap2)
}
}
}
fun processImage(bitmap: Bitmap, shouldResize: Boolean) {
bitmap.use { original ->
if (shouldResize) {
resizeBitmap(original, 500, 500).use { resized ->
uploadImage(resized)
}
} else {
uploadImage(original)
}
}
}
inline fun <T> Bitmap.use(block: (Bitmap) -> T): T {
return try {
block(this)
} finally {
try {
if (!this.isRecycled) {
this.recycle()
}
} catch (e: Exception) {
// recycle 실패는 무시
}
}
}
// Canvas 자동 관리
inline fun <T> Canvas.use(block: (Canvas) -> T): T {
return try {
block(this)
} finally {
this.restore()
}
}
// 사용 예시
canvas.use { c ->
c.save()
c.rotate(45f)
c.drawBitmap(bitmap, 0f, 0f, paint)
}
// inline을 사용하면 함수 호출 오버헤드가 없음
inline fun <T> Bitmap.use(block: (Bitmap) -> T): T {
// 컴파일 시 호출 위치에 직접 삽입됨
}
Kotlin의 확장 함수를 활용하면 Java의 try-with-resources와 동일한 안전성을 확보할 수 있습니다.
.use 확장 함수 정의 Android 앱의 안정성을 위해 꼭 적용해보세요!