TIL) 230408

Hanseul Lee·2023년 4월 9일
0

TIL

목록 보기
22/23

SafeArgs를 활용한 NavArgs의 argument 초기화하기?

safeArgs로 데이터를 전달 받고, 다른 화면으로 이동한 다음 백 버튼을 누르면 전달 받은 매개변수 때문에 아래와 같은 에러가 난다.

device-2023-04-08-105725.webm
채팅 화면을 클리어하고 세팅 화면으로 들어갔다가 백 버튼을 누르면 이전에 전달 받은 값이 남아있어 해당 값의 채팅 기록을 다시 불러오는 문제가 있다. 이 문제를 해결하기 위해서 NavArgs의 매개변수를 한 번 사용하면 초기화하는 방법을 알아보려 한다.

  1. 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()}")
        }
  2. 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")
}

0개의 댓글