본문 바로가기

Android/note

[Android] Fragment -> DialogFragment -> Fragment 데이터 처리

문제상황

 

1. List 를 보여주는 Fragment에서 data 추가를 위해 DialogFragment 호출

2. DialogFragment 에서 저장 버튼 클릭 시, interface 를 통해 List 를 보여주는 Fragment 로 데이터 전달

3. DialogFragment 종료

4. Room Database 에 insert 한 후, 최신 List 가져와 UI 에 보여주기

 

그런데 4번의 최신 List 를 가져와 UI 에 보여주기 부분이 제대로 이루어지지 않음


나의 예상

Fragment -> DialogFragment 이동 시, Fragment 의 생명주기 : onResume()

DialogFragment -> Fragment 이동 시, Fragment 의 생명주기 : onResume() -> onPause() -> onResume() 의 상태

결과

Fragment -> DialogFragment 이동 시, Fragment 의 생명주기 : onResume()

DialogFragment -> Fragment 이동 시, Fragment 의 생명주기 : onResume()


나의 예상 != 결과인 이유

A fragment that displays a dialog window, floating on top of its activity's window. This fragment contains a Dialog object, which it displays as appropriate based on the fragment's state.

공식홈페이지를 통해 DialogFragment는 activity 위에서 floating 되어 보여지므로 DialogFragment 가 종료되어도 Fragment 의 상태가 변하지 않는 다는 것을 알게되었다.


시도 1 - 실패

DialogFragment 의 onDismiss() 메소드를 오버라이드하여 dismiss 되었을 때 callback interface 를 호출하여 데이터 넘기기

 

시도 2 - 성공

DialogFragment 가 아닌 Activity 로 Dialog 형태로 만들어 보여주기

 

결과적으로는 기존의 Fragment 를 가지고 있는 Activity 가 아닌 다른 Activity(Dialog의 모습) 를 호출하여 registerForActivityResult 를 사용하여 data 받아 처리하였다.


ListFragment

class ListFragment : Fragment() {
	// Dialog(다른 Activity)에서 결과를 받아 처리하기 위한 변수
	private lateinit var getResultTopic: ActivityResultLauncher<Intent>
    
    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        getResultTopic = registerForActivityResult(
            ActivityResultContracts.StartActivityForResult()
        ) { result ->
            if (result.resultCode == Activity.RESULT_OK) {
                result.data?.let {
                    val topic = Topic(
                        it.getStringExtra("topic")!!,
                        it.getStringExtra("color")!!,
                        it.getStringExtra("date")!!)
                    (presenter as TopicPresenter).saveTopic(topic)
                }
            } else {
                println("===== getResultTopic - Failed =====")
            }
        }
    }
}

 

ListFragment 에서 data 추가 버튼 클릭 시

toolbar.setOnMenuItemClickListener { menu ->
	when (menu.itemId) {
		R.id.main_add -> {
			val topicAddIntent = Intent(view.context, TopicAddActivity::class.java)
			getResultTopic.launch(topicAddIntent)
            true
        }
		else -> false
	}
}

 

DialogActivity 에서 저장 버튼을 눌렀을 때(data 전달)

val moveTopicList = Intent(this, TopicListFragment::class.java)
moveTopicList.putExtra("topic", topic.topic)
moveTopicList.putExtra("color", topic.color)
moveTopicList.putExtra("date", topic.registDate)
setResult(Activity.RESULT_OK, moveTopicList)

 


배운점

1. DialogFragment 는 Fragment 의 lifecycle 에 영향을 미치지 않는다.

2. Fragment 의 pause / resume 은 기본적으로 Host Activity 를 따라간다.

2-1. Fragment 를 replace / remove 할 때에는 pause 상태를 가진다.

3. registerForActivityResult 사용