마스터Q&A 안드로이드는 안드로이드 개발자들의 질문과 답변을 위한 지식 커뮤니티 사이트입니다. 안드로이드펍에서 운영하고 있습니다. [사용법, 운영진]

안드로이드 컴포즈 이미지 설정하는거 질문합니다.

0 추천

버튼을 누르면 서버통신을 통해 변환된 이미지를 drawable 폴더 내에 있는 default 이미지로 변경하고 싶습니다. mutableStateof state를 사용하여 이미지 값을 관리하고 있는데, 특이한 에러는 없지만 앱을 실행하고 버튼 클릭시 뷰에 이미지 변경이 일어나지 않아서 질문합니다.

어떻게 코드를 고치면 되나요?

코드:

val responseImage = MyApplication.prefs.getData("image", "")
val decodedBytes = Base64.decode(responseImage, Base64.DEFAULT)
val decodedImage = BitmapFactory.decodeByteArray(decodedBytes, 0, decodedBytes.size)
 
val decodeFile: File? = File.createTempFile("temp", null, LocalContext.current.cacheDir)
val outputStream = FileOutputStream(decodeFile)
 
decodedImage?.compress(Bitmap.CompressFormat.PNG, 100, outputStream)
outputStream.close()
 
 
val defaultProfileImageBitmap = BitmapFactory.decodeResource(LocalContext.current.resources, R.drawable.defaultprofile)
 
val imageUri = rememberSaveable {
    mutableStateOf(decodeFile?.toUri())
}
 
var painter = rememberImagePainter(
    data = imageUri.value,
    builder = {
        if (imageUri.value == null) {
            placeholder(R.drawable.defaultprofile)
        }
    }
)
val onClickToDefaultImage = rememberImagePainter(data = defaultProfileImageBitmap)
 
Button(
    onClick = {
        painter = onClickToDefaultImage
        openDialog = false
    },
    shape = RoundedCornerShape(10.dp),
    modifier = Modifier
        .width(250.dp)
        .height(45.dp)
        .background(Color.White))
{
    Text(text = "기본 이미지로 변경")
}
 
Image(
    painter = painter,
    contentDescription = "profileImage",
    modifier = Modifier
        .size(150.dp)
        .padding(8.dp)
        .clickable {
            openDialog = !openDialog
        },
    contentScale = ContentScale.Crop
)

 

jongjoon (340 포인트) 님이 2023년 2월 22일 질문

2개의 답변

0 추천
그냥, imageUri.value = null로 만들면 되지 않나요.
spark (226,720 포인트) 님이 2023년 2월 22일 답변
알려주신 코드로 바꿔서 해봤는데, 뷰에 띄워지지 않습니다 ㅠㅠ
builder에서
if (imageUri.value == null) 부분을 없애면 어떻게 되나요?

var painter = rememberImagePainter(
    data = imageUri.value,
    builder = {
         placeholder(R.drawable.defaultprofile)
    }
)
알려주신 코드대로 조건문을 제거해서
builder = {
            placeholder(R.drawable.defaultprofile)
        }

이런 형태로 값을 넣어줬더니 에러가 발생합니다
ava.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.Boolean
0 추천

제가 Compose는 잘 다루지 못해서 좋은 답변을 드리지 못하겠네요. 다만 아래 코드가 동작하기는 합니다.

// profileImage를 파라미터로 받는 것이 더 좋을 것 같음.

val imageUri = rememberSaveable {
    mutableStateOf(decodeFile?.toUri())
}

val imageData: Any? = rememberSavable {
     mutableSateOf(imageUri)
}
  
Button(
    onClick = {
        imageData = R.drawable.defaultprofile
        ...
    },
    ...
{
    Text(text = "기본 이미지로 변경")
}
  
AsyncImage(
    imageData,
    placeholder = painterResource(R.drawable.defaultprofile)
    ...
)

분명 placeholder를 이용하는 방법이 있는 것 같은데, imageData = null로 하면 화면에 뷰들이 다 사라져 버리네요.
제건 참고용도만 사용하시면 좋을 것 같고, 약간의 힌드라도 되었으면 좋겠네요.

spark (226,720 포인트) 님이 2023년 2월 22일 답변
보통 프로필 사진을 바꾸는데 기본이미지 설정을 해준다면 어떤 로직으로 해야되나요?
일단 회원가입 성공시 기본적으로 서버로부터 응답값중 image의 값이 null값으로 와서 default 이미지를 보여줘야 되고, 나중에 프로필을 수정할때 갤러리에 있는 사진을 가져와서 바꾸고 서버로 리퀘하는 기능을 수행하면 바꾼 이미지로 바꾸는 로직으로 구성중인데요.

혹시 회원가입 성공시 default 이미지를 sharedPreferences 같은걸 사용해서 저장하고 프로필을 수정하기 전에는  default 이미지를 띄우고, 프로필 변경시 바뀐 이미지를 띄우고, "기본 이미지로 변경" 버튼을 누르면 sharedPreferences에 저장된 default 이미지를 불러와서 뷰에 띄우는 방식으로 해야될까요?
Compose state hoisting을 살펴보시는게 좋을 것 같습니다.
https://developer.android.com/jetpack/compose/state-hoisting
Compose의 기본원칙이 가능한  UI요소의 작은 단위의 함수로 나누고, 상태(데이터)는 아래로, 이벤트는 위로 올라가도록 하는 구조로 구성을 하도록 해야하는게 핵심입니다.
너무 어렵네요 ㅠㅠ
프로필 기본 사진으로 설정하는게 이렇게 까다롭고 어려울줄은 생각도 못했어요 ㅠㅠ
네. 컴포즈가 컴파일러 레벨에서 매직이 일어나는 거라 내부를 어느정도 이해하지 않으면 상당히 어려운 라이브러리입니다. 제대로 사용하려면 상당한 시간이 걸리는 라이즈러리예요. 저는 요즘 막 보기 시작했는데, ios Swift에 비하면 배워야할 게 훤씬 더 많은 거 같아요. Compose internal이란 책이 있는데 이거를 보면 컴포즈 내부가 얼마나 복잡한지 알 수 있어요. 그래서인지 커뮤니티에서는 아직 구들의 대대적인 광고에 비해서는 도입이 만히 느리다는 느낌예요.다만 jrtbrain에서 compose프로젝트를 하고 있는데 kotlin multiplatform처럼 ui도 android, ios, web, window, linux등을 jetpack compose를 사용하는 방식으로 코드를 한번만 작성하면 해당 플랫폼에 대한 코드를 만들어주는 제품을 만들고 있어요. 이게 정식 출시된다면 배울만한 가치가 있긴 할 겁니다
...