๋ชฉ์ฐจ
๋ค์ด๊ฐ๊ธฐ ์ ์
์ค๋์ ์ด์ ํ๋ฃจ๋์ ํ๋ก์ ํธ์ Navigation ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ ์ฉํ ๊ณผ์ ์ ์ ๋ฆฌํด๋ณด๋ ค๊ณ ํ๋ค.
์ฒ์ ์ฌ์ฉํด๋ณธ ๋ด์ฉ์ด๋ผ์ ๊น๋จน์ง ์๊ธฐ ์ํด ๊ทธ๋ฆฌ๊ณ ๊ธฐ์กด ๋ฐฉ์ ๋๋น ์ข์๋ ์ ์ ๊ธฐ๋กํด๋๊ธฐ ์ํด ์ ์ด๋ณด๊ฒ ๋
๊ธฐ์กด ๋ฐฉ์ (์ด๋ & ๋ฐ์ดํฐ ์ ๋ฌ)
์ฐ์ ์ฐ๋ฆฌ ํ์ ๊ตฌ์กฐ๋ฅผ ๋ณด๋ฉด ์๋์ ๊ฐ๋ค.
- ์กํฐ๋นํฐ์ ํ๋๊ทธ๋จผํธ ๊ธฐ์ค
์กํฐ๋นํฐ๋ก ๋ง๋ ๊ธฐ์ค์ ํ๋ฉด ๋ณ๊ฒฝ ์ ๋ณด์ฌ์ผํ๋ ํฐ ๋ ์ด์์์ผ๋ก ์ก์๋ค.
๋ฉ์ธ ์กํฐ๋นํฐ์ ๊ฒฝ์ฐ ๋ฐํ ๋ค๋น๊ฒ์ด์ ๋ฐ๊ฐ ํ๋๊ทธ๋จผํธ๊ฐ ๊ต์ฒด๋จ์๋ ๊ณ์ ํ๋ฉด์ ๋ํ๋์ผํ๊ณ , ๊ฐ์๋ฌธ์ ์์ฑํ๋ ํ๋ฉด์์๋ ํด๋น ๋ฐํ ๋ค๋น๊ฒ์ด์ ๋ฐ๊ฐ ํ๋ฉด ์์์ ์กด์ฌํ์ง ์๊ธฐ ๋๋ฌธ์ ๋ณ๋์ ์กํฐ๋นํฐ๋ฅผ ๋ง๋ค์ด์ฃผ์๋ค.
ํฌ๊ฒ MainActivity์์๋ ๋ฐํ
๋ค๋น๊ฒ์ด์
๋ฐ์ FragmentContainerView๋ฅผ ๊ฐ์ง๊ณ ์๊ณ ,
๋ฐํ
๋ค๋น๊ฒ์ด์
์์ดํ
์ ํด๋ฆญ๊ณผ ํ๋ฉด ์์ ํด๋ฆญ์ ํตํด ํ๋๊ทธ๋จผํธ ์ด๋ ๋ฐ ํ๋ฉด ์ด๋์ ์ฒ๋ฆฌํ๊ณ ์๋ค.
์ด ๋ FragmentManager์ ํตํด ์ด๋์ ์ฒ๋ฆฌํด์ฃผ์๋๋ฐ, ํ๋๊ทธ๋จผํธ A์์ ํ๋๊ทธ๋จผํธ B๋ก ์ด๋ํด์ผํ ๊ฒฝ์ฐ ์กํฐ๋นํฐ์ ๊ตฌํํ ๋ฉ์๋๋ฅผ ํธ์ถ(1)ํ์ฌ ํ๋๊ทธ๋จผํธ B๋ก ์ด๋(2)ํ๋ ๋ฐฉ์์ด์๋ค.
// ์กํฐ๋นํฐ์ ๊ตฌํํ๋ ํ๋๊ทธ๋จผํธ ์ด๋
fun navigateToReportFragment() {
supportFragmentManager.beginTransaction()
.add(R.id.main_fragment_container_view, ReportFragment.newInstance())
.addToBackStack(null)
.commit()
// ํ๋๊ทธ๋จผํธ ์ด๋์ด ํ์ํ ๋ ํ๋๊ทธ๋จผํธ์์๋ ์๋์ ๊ฐ์ด ๋ฉ์๋๋ฅผ ํธ์ถํด์ฃผ์๋ค.
binding.btnReply.setOnClickListener {
(activity as MainActivity).navigateToReportFragment(reportId)
๋ง์ฝ ํ๋๊ทธ๋จผํธ A -> B๋ก์ ์ด๋ ์ค ๋ฐ์ดํฐ๋ฅผ ์ ๋ฌํด์ผํ๋ค๋ฉด ์ด๋ ์ ๋ฐ์ดํฐ๋ฅผ ๋ฃ์ด์ฃผ๋ ๋ฐฉ์์ด์๋ค.
// ์กํฐ๋นํฐ์ ์์ฑํด๋ ํ๋๊ทธ๋จผํธ ์ด๋
fun navigateToDetailMovieFragment(movieID: Int) {
supportFragmentManager.beginTransaction()
.add(R.id.main_fragment_container_view, MovieDetailFragment.newInstance(movieID))
.addToBackStack(null)
.commit()
}
// ํ๋๊ทธ๋จผํธ์์ ํด๋ฆญ ์ด๋ฒคํธ ๋ฐ์ ์ ๋ฐ์ดํฐ์ ํจ๊ป ํ๋๊ทธ๋จผํธ ์ด๋
override fun onClick(position: Int) {
val movieId = movie[position].id
(activity as MainActivity).navigateToDetailMovieFragment(movieId)
}
}
๋ฃ์ด์ค ๋ฐ์ดํฐ๋ ์ด๋ํ ํ๋๊ทธ๋จผํธ์์ ์ ๊ทผํ ์ ์์๋ค.
val movieId = arguments?.getInt("MOVIE_ID")
์ด๋ MovieDetailFragment ๊ฐ์ฒด ์์ฑ ์ ํ์ํ argument๋ฅผ ๋ถ์ฌ ๋ฐํํด์ฃผ์๋ค.
companion object {
// MovieDetailFragment ๊ฐ์ฒด๋ฅผ ์์ฑํ๊ธฐ ์ํ ๋ฉ์๋
fun newInstance(
movieID: Int,
): MovieDetailFragment {
// DetailFragment ๊ฐ์ฒด๋ฅผ ์์ฑํ๋ค
val fragment =
MovieDetailFragment().apply {
// ๊ทธ๋ฆฌ๊ณ ๊ทธ ํ๋๊ทธ๋จผํธ์ movieID๋ผ๋ bundle(arguments)๋ฅผ ๋ถ์ฌ์ค๋ค.
arguments =
Bundle().apply {
putInt("MOVIE_ID", movieID)
}
}
// argument๊ฐ ๋ถ์ด์๋ ํ๋๊ทธ๋จผํธ๋ฅผ ๋ฐํํ๋ค.
return fragment
}
}
Navigation ์ ์ฉ
- ๋ฐํ ๋ค๋น๊ฒ์ด์ ๊ณผ ์ฐ๊ฒฐ
ํ๋๊ทธ๋จผํธ ๊ฐ ๋ค๋น๊ฒ์ด์ ์ ๊ธฐ์กด์๋ ๋ฐํ ๋ค๋น๊ฒ์ด์ ๋ทฐ ์ด๋ฒคํธ๋ฅผ ๋ทฐํ์ด์ ๋ก ์ฒ๋ฆฌํด์ฃผ๊ณ ์์๋ค.
๊ทธ๋ฐ๋ฐ Navigation๊ณผ ๋ฐํ ๋ค๋น๊ฒ์ด์ ์ ์ฐ๋ํด์ ๋์ฑ ์งง์ ์ฝ๋๋ก ์ด๋ฒคํธ๋ฅผ ์ฒ๋ฆฌํ ์ ์์ด์ ํธํ๋ค.
val navHostFragment =
// supportFragmentManager: ์กํฐ๋นํฐ ๋ด์์ ํ๋๊ทธ๋จผํธ์ ์ํธ์์ฉํ ์ ์๊ฒ ํด์ค๋ค.
// Id๋ก ๋ ์ด์์ ํ์ผ์ ์ ์ํด์ค NavHostFragment๋ฅผ ์ฐพ๋๋ค.
supportFragmentManager
.findFragmentById(R.id.main_fragment_container_view) as NavHostFragment
// navController : ์ฑ ํ์ ์ฒ๋ฆฌ ๋ด๋น ๊ฐ์ฒด, ๋ฐฑ์คํ
๊ณผ ์ฌ๋ฌ ํ๋๊ทธ๋จผํธ ๊ฐ ํ์์ ๊ด๋ฆฌํ๋ค.
navController = navHostFragment.navController
binding.navBar.setupWithNavController(navController)
๊ทธ๋ฆฌ๊ณ ๋ฐํ ๋ค๋น๊ฒ์ด์ ์ ์์ดํ ๊ณผ ์ด๋ํ ํ๋ฉด์ ์ฐ๊ฒฐํด์ฃผ์๋ค.
์ด ๋ ์ฃผ์ํ ์ !!!
itemId์ nav_graph์์ ์ ์ํด์ค ํ๋๊ทธ๋จผํธ์ id๊ฐ ๋์ผํด์ผ ์ ์์๋ํ๋ค.
๋๋ ๋ณ๊ฐ๋ผ๊ณ ์๊ฐํ์๋๋ฐ id๊ฐ ๋ฌ๋ผ์ ํด๋ฆญํด๋ ํ๋๊ทธ๋จผํธ๋ ํ๋ฉด์ด ์ด๋ํ์ง ์์๋ค.. ใ ใ ใ
binding.navBar.setOnItemSelectedListener {
when (it.itemId) {
R.id.allMovieReportFragment -> {
if (navController.currentDestination?.id != R.id.allMovieReportFragment) {
navController.navigate(R.id.allMovieReportFragment)
}
return@setOnItemSelectedListener true
}
R.id.myPageFragment -> {
if (navController.currentDestination?.id != R.id.myPageFragment) {
navController.navigate(R.id.myPageFragment)
}
return@setOnItemSelectedListener true
}
R.id.writeActivity -> {
val intent = Intent(this, WriteActivity::class.java)
startActivity(intent)
return@setOnItemSelectedListener true
}
else -> {
return@setOnItemSelectedListener false
}
}
}
id๊ฐ ๋ง์ง ์์ผ๋ฉด ์๋์ ๊ฐ์ ์๋ฌ๊ฐ ๋ฐ์ํ๋ฉฐ ์ด๋ฒคํธ๊ฐ ์ผ์ด๋์ง ์๋๋ค.
java.lang.IllegalArgumentException: Navigation action/destination com.example:id/navigateToWriteReport cannot be found from the current destination Destination(com.example:id/writeReportFragment) label=WriteReportFragment class=WriteReportFragmenIgnoring onNavDestinationSelected for MenuItem id/write as it cannot be found from the current destination Destination(com.example:id/allMovieReportFragment) label=AllMovieReportFragment class=com.example.ui.report.all.AllMovieReportFragment
- ํ๋๊ทธ๋จผํธ ์ด๋
์ํ๋ฅผ ํด๋ฆญํ์ ๋ ์ํ์ ์์ธ ์ ๋ณด๋ฅผ ๋ณผ ์ ์๋ ํ๋๊ทธ๋จผํธ๋ก ์ด๋ํ๊ธฐ ์ํด์๋ ์๋์ ๊ฐ์ด ์ฝ๋๋ฅผ ์์ฑํด์ฃผ๋ฉด ๋๋๋ฐ
์ฌ๊ธฐ์ navigateToMovieDetail์ nav_graph.xml ํ์ผ์์ action์ ์ ์ํด์ค id๊ฐ์ด๋ค.
๋๊ฒจ์ค์ผํ arguement๊ฐ ์๋ค๋ฉด ํจ๊ป ๋๊ฒจ์ฃผ๋ฉด ๋๋ค.
// findNavController() : ์ด ํ๋๊ทธ๋จผํธ ๋๋ ํ๋๊ณผ ์ฐ๊ด๋ NavController๋ฅผ ์ฐพ๋๋ค.
// NavController : ์ฑ ๋ด ํ์์ ๊ด๋ฆฌํ๊ณ ํ์ ๊ทธ๋ํ์ ์ ์๋ ํ๋๊ทธ๋จผํธ, ์กํฐ๋นํฐ ์ฌ์ด๋ฅผ ์ด๋ํ๋๋ฐ ๋์์ ์ค๋ค.
private val navController by lazy { findNavController() }
private fun navigateToMovieDetail(movieId: Int) {
val action = AllMovieReportFragmentDirections.navigateToMovieDetail(movieId)
navController.navigate(action)
}
MovieDetailFragment์์ ๋ฐ์ movieId๋ฅผ ์ด์ฉํ๋ ค๊ณ ํ๋ค๋ฉด args ๋ณ์๋ฅผ ์ ์ธํด์ฃผ๊ณ args.movieId์ ๊ฐ์ด ์ด์ฉํ ์ ์๋ค.
val args: MovieDetailFragmentArgs by navArgs()
//MovieDetailFragmentArgs : Safe Args๋ฅผ ์ฌ์ฉํ ๋ ์์ฑ๋๋ ํด๋์ค์ด๋ค.
// MovieDetailFragment์ ์์ ํ๊ฒ ์ ํ๋ณ๋ก ์ ๋ฌ๋ ์ธ์๊ฐ ํฌํจ๋์ด ์์ด ์๋์ผ๋ก ๋ฒ๋ค์ ์ฒ๋ฆฌํ์ง ์์๋ ์ธ์๋ฅผ ๊ฒ์ํ ์ ์๋ฐ.
val args: MovieDetailFragmentArgs by navArgs()
lifecycleScope.launch {
viewModel.searchMovieDetail(args.movieId)
}
safe args ๋ฐฉ์์ ์ฌ์ฉํ์ ๋ ์ข์๋ ์
ํ๋๊ทธ๋จผํธ ๊ฐ ์ด๋์ ๋์ฑ ๊ฐํธํ๊ฒ ํ๊ธฐ ์ํด Navigation์ ์ ์ฉํ๋ค๋ณด๋ ์ธ์๋ฅผ ์ ๋ฌํ๋ ๊ฒ๋ํ ์ง์ํ๋ค๋ ๊ฒ์ ์๊ฒ๋์๊ณ , ๋ค์ ๋ฒ๊ฑฐ๋กญ๋ ์ธ์ ์ ๋ฌ ๋ฐฉ์๋ํ safe args๋ฅผ ์ ์ฉํด์ ๊ตฌํํด๋ณด์๋ค.
๊ธฐ์กด bundle ๋ฐฉ์์์๋ ํค๋ฅผ ์ง์ ์ฌ๋ฌ ๋ฒ ์์ฑํด์ค์ผํ๋๋ฐ ์ด ๋ ์๋ชป ์์ฑํ ๊ฒฝ์ฐ ๋ฐ์ดํฐ๊ฐ ์ ๋๋ก ์ค์ง ์๋๋ค.
๋๋ ๋ช ๋ฒ ํค ์ฒ ์๋ฅผ ์๋ชป ์์ฑํ์ฌ ๋ฐ์ดํฐ๊ฐ ์ค์ง ์์๋ ์ ์ด ๋ช ๋ฒ์์๊ณ , ๊ดํ ๋ค๋ฅธ ๋ถ๋ถ์ ๋ฌธ์ ๊ฐ ์๋ ์ค ์๊ณ ์๊ฐ์ ํ๋นํ๋ ๋๊ฐ ์์๋ค.
// ๋ฒ๋ค ๋ฐฉ์
val movieID = arguments?.getInt("MOVIE_ID") // Needs to use the correct key
// safe agrs ๋ฐฉ์
private val args: ReportThumbnailFragmentArgs by navArgs()
args.movieName
๊ทธ๋ฌ๋ safe args ๋ฐฉ์์์๋ nav_graph.xml ์์์ argument๋ฅผ ์ ์ํด์ฃผ๊ณ ๊ฐ๋ฐ ์ค์๋ ๋ฌธ์์ด ํํ์ ํค๋ฅผ ์๋์ผ๋ก ์์ฑํด์ฃผ์ง ์์๋ ๋๋ค.
์ ํ์ด๋ ํค ์ ํ์ด nav_graph.xml ์์ ์์ฑํ ๊ฒ๊ณผ ๊ฐ์์ง๋ ์์์ ํด์ฃผ๊ธฐ ๋๋ฌธ์ ํธํ๋ค ใ ใ
๋ฌด์๋ณด๋ค nav_graph.xml ํ์ผ 1๊ฐ๋ง ๊ฒํ ํ๋ฉด ๋๋ค๋ ์ ์ด ๊ฐ์ฅ ํธํ๋ค.
Navigation๋ ๊ฐํธํ๊ฒ ํ๋ฉด์ ์ด๋ํ๊ณ ๋ฐ์ดํฐ๋ฅผ ์ ์กํ ์ ์์ด์ ํธํ๋ค
๊ธฐ์กด ๋ฐฉ์์ ์ฌ์ฉํ๊ณ Navigation์ ์ฌ์ฉํ๋ ๋์ฑ ์ฐจ์ด๊ฐ ๋๊ปด์ก๋ค.
๊ทธ๋ผ Navigation ์ ์ฉ ๊ณผ์ ๋์
'๐ค2024 ์๋๋ก์ด๋ > ๐ฟ ์ํ ํ๋ก์ ํธ ๊ฐ๋ฐ ์ผ์ง' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
๐ [Android Repository Pattern]์ ์ฌ์ฉํ๋ ์ด์ ์์๋ณด๊ธฐ! (3) | 2024.11.18 |
---|---|
โบ๏ธAndroid : flow๋ฅผ ์์ฐจ์ ์ผ๋ก ์ฌ์ฉํด๋ณด์~! (2) | 2024.11.04 |
๋ฌดํ์คํฌ๋กค์ Paging3 ์ ์ฉํ๊ธฐ (9) | 2024.10.13 |
๐จ๋ฆฌ์ฌ์ดํด๋ฌ๋ทฐ ์คํฌ๋กค ์ ๋ํ๋ ๊ฒฝ๊ณ (3) | 2024.10.13 |
๐๋ฌดํ ์คํฌ๋กค ์์ ๊ตฌํํด๋ณด๋ค. (5) | 2024.10.12 |