safeArgs로 데이터를 전달 받고, 다른 화면으로 이동한 다음 백 버튼을 누르면 전달 받은 매개변수 때문에 아래와 같은 에러가 난다.
device-2023-04-08-105725.webm
채팅 화면을 클리어하고 세팅 화면으로 들어갔다가 백 버튼을 누르면 이전에 전달 받은 값이 남아있어 해당 값의 채팅 기록을 다시 불러오는 문제가 있다. 이 문제를 해결하기 위해서 NavArgs의 매개변수를 한 번 사용하면 초기화하는 방법을 알아보려 한다.
NavArgs.toBundle().clear()
private fun retrieveMessageList() {
Log.d("ARGUMENT_TEST", "function 진입 :: ${argsFromList.chatListId}")
Log.d("ARGUMENT_TEST", "toBundle() :: ${argsFromList.toBundle()}")
chatViewModel.clearMessageList()
argsFromList.chatListId.let {id ->
listViewModel.chatListId(id).observe(this.viewLifecycleOwner) {
it?.chatList?.let { it1 -> chatViewModel.retrieveMessageListFromList(it1) }
chatViewModel.messageList.value?.let { it1 -> messageAdapter.setMessageList(it1) }
}
}
argsFromList.toBundle().clear()
Log.d("ARGUMENT_TEST", "clear 후 :: ${argsFromList.chatListId}")
Log.d("ARGUMENT_TEST", "toBundle() :: ${argsFromList.toBundle()}")
}
NavArgs.toBundle().remove()
이 메서드는 특정 매개변수를 지우는데, nav graph에서 디폴트값을 지정해줘야 한다. 그렇지 않으면 매개변수를 찾을 수 없어서 앱이 다운된다.
private fun retrieveMessageList() {
Log.d("ARGUMENT_TEST", "function 진입 :: ${argsFromList.chatListId}")
Log.d("ARGUMENT_TEST", "toBundle() :: ${argsFromList.toBundle()}")
chatViewModel.clearMessageList()
argsFromList.chatListId.let {id ->
listViewModel.retrieveChatList(id).observe(this.viewLifecycleOwner) {
it?.chatList?.let { it1 -> chatViewModel.retrieveMessageListFromList(it1) }
chatViewModel.messageList.value?.let { it1 -> messageAdapter.setMessageList(it1) }
}
}
argsFromList.toBundle().remove("retrieveChatListId")
Log.d("ARGUMENT_TEST", "clear 후 :: ${argsFromList.chatListId}")
Log.d("ARGUMENT_TEST", "toBundle() :: ${argsFromList.toBundle()}")
}
하지만 두 방법 모두 내 의도대로 삭제되지 않았다. 두 코드 다 로그를 확인하면 여전히 같은 값을 가져오고 있다는 걸 알 수 있다.
왜냐하면 Args.fromBundle(Bundle)
함수를 사용하여 Bundle
에서 Args
객체를 만들 때, Bundle
은 내부 상태를 저장하기 위한 매개변수 목록을 유지하기 때문이다. argsFromList
객체의 toBundle()
함수는 내부 Bundle
객체의 복사본을 반환한다는 말이다. 아무리 clear()와 remove()를 해도 지워지지 않았던 이유는, 실제 객체의 값을 처리한 게 아니라 복사본의 값을 처리했기 때문이다.
그래서 다음 코드처럼 하면 의도대로 삭제가 가능하다.
private val argsFromList: ChatFragmentArgs by navArgs()
private fun retrieveMessageList() {
Log.d("ARGUMENT_TEST", "function 진입 :: ${argsFromList.chatListId}")
Log.d("ARGUMENT_TEST", "toBundle() :: ${argsFromList.toBundle()}")
chatViewModel.clearMessageList()
argsFromList.chatListId.let { id ->
listViewModel.retrieveChatList(id).observe(this.viewLifecycleOwner) {
it?.chatList?.let { it1 -> chatViewModel.retrieveMessageListFromList(it1) }
chatViewModel.messageList.value?.let { it1 -> messageAdapter.setMessageList(it1) }
}
}
val newBundle = argsFromList.toBundle().apply {
remove("chatListId")
}
val newArgs = ChatFragmentArgs.fromBundle(newBundle)
Log.d("ARGUMENT_TEST", "clear 후 :: ${newArgs.chatListId}")
Log.d("ARGUMENT_TEST", "toBundle() :: ${newArgs.toBundle()}")
}
하지만 또 다른 문제가 일어난다.
💡 Type 'NavArgsLazy' has no method 'setValue(ChatFragment, KProperty<*>, ChatFragmentArgs)' and thus it cannot serve as a delegate for var (read-write property)navArgs를 새롭게 만든 navArgs로 교체하기 위해서 argsFromList
변수를 val에서 var로 바꾸니 위와 같은 오류 메세지가 뜬다. 생각해보면 안전한 데이터 전달을 위해서 safeArgs를 활용하는 건데, read-write를 허용하게 되면 목적이 흐려지게 된다. 결과적으로 safeArgs를 이용한 NavArgs의 매개변수 초기화는 불가능하다.
import java.util.*
fun main() {
val currentDate = Date()
println("현재 날짜 및 시간: $currentDate")
}
import java.util.*
import java.text.SimpleDateFormat
fun main() {
val currentTimeMillis = System.currentTimeMillis() // 현재 밀리초 값 가져오기
val currentDate = Date(currentTimeMillis) // 밀리초 값을 Date 객체로 변환
val dateFormat = SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS") // 날짜 포맷 지정 (밀리초 포함)
val formattedDate = dateFormat.format(currentDate) // 밀리초 값을 포맷팅하여 문자열로 변환
println("현재 시간 (밀리초): $currentTimeMillis")
println("현재 시간 (포맷팅): $formattedDate")
}