빙수왕의 개발일지

Activity에서 Fragment로 값 전달하기 본문

개발/Android

Activity에서 Fragment로 값 전달하기

빙수킹 2020. 8. 6. 23:02

Q) MainActivity에서 DestinationFragment로 "value1"과 "value2"를 전달하자

 

1. 그저그런방법

- 내가 한 비루한 방법.. 이렇게는 하지말자.

 

MainActivity.kt

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        
        val fragment = DestinationFragment()
        fragment.arguments = bundleOf(Pair(DestinationFragment.VALUE_ONE, "value1"), Pair(DestinationFragment.VALUE_TWO, "value2"))
        supportFragmentManager.beginTransaction().replace(R.id.fl_fragment, fragment).commit()
    }
}

 

DestinationFragment.kt

class DestinationFragment : Fragment() {

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        return inflater.inflate(R.layout.fragment_destination, container, false)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        
        val valueOne = arguments?.getString(VALUE_ONE)
        val valueTwo = arguments?.getString(VALUE_TWO)
    }

    companion object {
        private const val VALUE_ONE = "VALUE_ONE"
        private const val VALUE_TWO = "VALUE_TWO"
    }
}

 

2. 훨씬 좋은 방법

* fragment 객체를 만드는 방법이 다르다.

- fragment가 같은게 2개 이상 생기는걸 방지하기 위해 supportFragmentManager.findFragmentById(id) 를 통해 있는지 찾고, 없는 경우에만 add 또는 replace 해준다.

- fragment가 있는지 찾는 메소드를 DestinationFragment의 companion object에 추가하여 재사용성을 높여주었다.

- newInstance메소드를 DestinationFragment의 companion object에 추가하여 fragment 객체를 만들 수 있도록 했는데, 이렇게 하면 장점은 화면이 넘어갈 때 놓칠 수 있는 VALUE_ONE과 VALUE_TWO를 강제하여 실수를 방지할 수 있다!

- null체크를 let으로 해주었다.

- @JvmStatic: getter, setter을 만들어주는 annotation

 

MainActivity.kt

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        val fragment: DestinationFragment? =
            DestinationFragment.findFragment(supportFragmentManager, R.id.contentFrame)

        if (fragment == null) {
            DestinationFragment.newInstance("value1", "value2").let { fragment ->
                supportFragmentManager.beginTransaction()
                    .add(R.id.contentFrame, fragment)
                    .commit()
            }
        }
    }
}

 

DestinationFragment.kt

class DestinationFragment : Fragment() {

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        return inflater.inflate(R.layout.fragment_destination, container, false)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        arguments?.let {
            val valueOne = it.getString(VALUE_ONE)
            val valueTwo = it.getString(VALUE_TWO)
        }
    }

    companion object {
        private const val VALUE_ONE = "VALUE_ONE"
        private const val VALUE_TWO = "VALUE_TWO"

        @JvmStatic
        fun newInstance(valueOne: String, valueTwo: String) =
            DestinationFragment().apply {
                arguments = bundleOf(
                    VALUE_ONE to valueOne,
                    VALUE_TWO to valueTwo
                )
            }

        fun findFragment(fragmentManager: FragmentManager, @IdRes id: Int): DestinationFragment? {
            return fragmentManager.findFragmentById(id) as? DestinationFragment
        }
    }
}

 

3. 더더좋은방법

Activity에서와 마찬가지로 findFragment, replaceFragment 역할을 하는 extension 함수를 정의하고, 이를 활용하여 객체를 만드는 코드를 companion object에 넣어주면 된다.

코드는 생략.