📌참고자료: Why to use Fragment Arguments in Android | Medium
Fragment Recreation
- Fragment recreation:
when fragment instance has to be destroyed and be initiated again
-> fragment constructer will be called again
-> fragment will live a whole new lifecycle- Configuration change triggers recreation
-> recreation of currently visible fragment (and activity)class MainActivity : AppCompatActivity(){ override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) if (savedInstanceState == null) { supportFragmentManager.beginTransaction() .replace(R.id.container, RecreationExampleFragment()) .commit() } } }
- Activity will create fragment...
- in onCreate()
- when restoring activity's state (savedInstanceState)
Don'ts when using fragments
- 우리가 필요로하는 데이터를 파라미터로 갖는 cunstom constructor를 정의하는 경우
-> not guaranteed to be always safe
-> The android system requires each fragment to have a default constructor with no parameter
(default constructor is called on fragment recreation)class BadFragment1( // will crash, on recreation because no default constructor is defined private val textToShow: String ): Fragment()
- 우리가 필요로하는 데이터를 프로퍼티로 갖도록 정의하는 경우
-> value will be lost in fragment recreationclass BadFragment2: Fragment() { // Will be reset to empty string after recreation var textToShow: String = "" }
Fragment arguments
- It is strongly recommended to supply arguments with setArguments and later retrieved by the Fragment with getArguments
-> These arguments are automatically saved and restored alongside the Fragment- Fragment argument로 사용할 수 있는 data type에 제한 존재
- Only simple data types are supported (ex. String, Int, ...)
- Parcelables, Serializables
- newInstance() 패턴
class GoodFragment: Fragment() { // retrieve value from arguments in custom getter private val textToShow: String get() = requireArguments().getString(ARG_TEXT_TO_SHOW) ?: throw IllegalArgumentException("Argument $ARG_TEXT_TO_SHOW required") companion object { // the name for the argument private const val ARG_TEXT_TO_SHOW = "argTextToShow" // Use this function to create instances of the fragment // and set the passed data as arguments fun newInstance(textToShow: String) = GoodFragment().apply { arguments = bundleOf( ARG_TEXT_TO_SHOW to textToShow ) } } }
interface FragmentDataListener {
fun onDataReceived(data: String)
}
class SecondFragment : Fragment() {
private var listener: FragmentDataListener? = null
//...
override fun onAttach(context: Context) {
super.onAttach(context)
if (context is FragmentDataListener) {
listener = context
} else {
throw RuntimeException("$context must implement FragmentDataListener")
}
}
//...
override fun onDestroyView() {
super.onDestroyView()
_binding = null
listener = null
}
}
val dataToSend = "Hello from SecondFragment!"
listener?.onDataReceived(dataToSend)
class MainActivity : AppCompatActivity(), FragmentDataListener {
//...
override fun onDataReceived(data: String) {
// Fragment에서 받은 데이터를 처리
Toast.makeText(this, data, Toast.LENGTH_SHORT).show()
}
}