๐ก์๋๋ก์ด๋์์ ๋ฆฌ์์ค๋ฅผ ์ฝ๊ฒ ๊ด๋ฆฌํ๊ธฐ ์ํด ์ฌ์ฉํ๋ Resource Provider์ ๋ํ์ฌ ๊ธฐ๋กํ์์ต๋๋ค.
Resource Provider
- Resource Provider๋ ์๋๋ก์ด๋์์ ๋ฆฌ์์ค๋ฅผ ๋ ์ฝ๊ฒ ๊ด๋ฆฌํ๊ณ ํ ์คํธ ๊ฐ๋ฅ์ฑ์ ๋์ด๊ธฐ ์ํด ์ฌ์ฉํ๋ ํจํด์ ๋๋ค.
- XML๋ฆฌ์์ค(๋ฌธ์์ด, ์์, ๋ฐฐ์ด ๋ฑ)์ ๊ฐ์ ๋ฆฌ์์ค๋ฅผ ์ฝ๋ ๋ด์์ ์ฃผ์ ํ๊ณ ViewModel์ด๋ ๋ค๋ฅธ ํด๋์ค์์ ์ฌ์ฉํ๋ฉด์๋ ๋ฆฌ์์ค์ ์ง์ ์ ๊ทผํ์ง ์๋๋ก ๋ง๋ค์ด์ค๋๋ค.
ViewModel์ด๋ Repository์์๋ Context์ ์ง์ ์ ๊ทผํ๋ ๊ฒ์ด ๊ถ์ฅ๋์ง ์์ต๋๋ค. Resource Provider ํจํด์ ์ฌ์ฉํ์ฌ ๋ฆฌ์์ค์ ๋ํ ์ ๊ทผ์ ์ธํฐํ์ด์ค๋ก ์ถ์ํํ ์ ์์ต๋๋ค.
Resource Provider์ ์ญํ
- Context์ ๋ํ ์์กด์ฑ์ ์ค์
๋๋ค.
- ๋ฆฌ์์ค๋ฅผ ์ง์ Context์์ ๋ถ๋ฌ์ค๋ ๋์ , Resource Provider๋ฅผ ํตํด ๋ฆฌ์์ค๋ฅผ ๊ฐ์ ธ์ด์ผ๋ก์จ Context์ ๋ํ ์์กด์ฑ์ ์ค์ผ ์ ์์ต๋๋ค.
- ํ
์คํธ ์ฉ์ด์ฑ์ ์ฆ๊ฐ์ํต๋๋ค.
- Resource Provider๋ฅผ ์ฌ์ฉํ๋ฉด Mock ๋ฆฌ์์ค๋ฅผ ์ฃผ์ ํ ์ ์์ด, ๋จ์ ํ ์คํธ๊ฐ ์ฌ์์ง๋๋ค.
Resource Provider ๊ตฌํ
ResourceProvider Interface
- ๋ฆฌ์์ค๋ฅผ ์ ๊ณตํ๋ ์ธํฐํ์ด์ค๋ฅผ ์ ์ํ์ฌ, ๋ค์ํญ ๋ฆฌ์์ค๋ฅผ ๊ฐ์ ธ์ค๋ ์ญํ ์ ๋ถ์ฌํฉ๋๋ค.
interface ResourceProvider {
fun getString(resId: Int): String
fun getString(resId: Int, vararg formatArgs: Any): String
fun getColor(resId: Int): Int
fun getDrawable(resId: Int): Drawable?
}
ResourceProviderImpl
- ์ค์ ๊ตฌํ์ฒด์์ Context๋ฅผ ์ฌ์ฉํ์ฌ ๋ฆฌ์์ค๋ฅผ ๊ฐ์ ธ์ค๋ ์ฝ๋๋ฅผ ๊ตฌํํฉ๋๋ค.
class ResourceProviderImpl(private val context: Context) : ResourceProvider {
override fun getString(resId: Int): String {
return context.getString(resId)
}
override fun getString(resId: Int, vararg formatArgs: Any): String {
return context.getString(resId, *formatArgs)
}
override fun getColor(resId: Int): Int {
return ContextCompat.getColor(context, resId)
}
override fun getDrawable(resId: Int): Drawable? {
return ContextCompat.getDrawable(context, resId)
}
}
ViewModel์์ ํ์ฉ
- ViewModel์์๋ Context์ ์ง์ ์ ๊ทผํ์ง ์๊ณ , ResourceProvider๋ฅผ ์ฃผ์ ๋ฐ์ ๋ฆฌ์์ค๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค.
class MyViewModel(private val resourceProvider: ResourceProvider) : ViewModel() {
fun getWelcomeMessage(): String {
return resourceProvider.getString(R.string.welcome_message)
}
fun getFormattedMessage(name: String): String {
return resourceProvider.getString(R.string.hello_message, name)
}
}
- ์ด๋ฅผ ํ์ฉํ๋ฉด Context์ ์์กดํ์ง ์๊ณ ๋ฆฌ์์ค์ ์ ๊ทผ์ด ๊ฐ๋ฅํด์ง๋๋ค.
์์กด์ฑ ์ฃผ์ ๋ผ์ด๋ธ๋ฌ๋ฆฌ ํ์ฉ
- Hilt๋ Dagger๋ฅผ ํ์ฉํ ์์กด์ฑ ์ฃผ์ ๋ ์ ์ฉํ๊ฒ ํ์ฉํ ์ ์์ต๋๋ค.
@HiltViewModel
class MyViewModel @Inject constructor(
private val resourceProvider: ResourceProvider
) : ViewModel() {
// ViewModel ์ฝ๋...
}
ํ ์คํธ ๋ฐฉ์์?
- ํ ์คํธ์์ ResourceProvider์ Mock์ ์์ฑํ์ฌ ํ ์คํธ๋ฅผ ์งํํ ์ ์์ต๋๋ค.
class FakeResourceProvider : ResourceProvider {
override fun getString(resId: Int): String {
return when (resId) {
R.string.welcome_message -> "Welcome!"
else -> "Unknown"
}
}
override fun getString(resId: Int, vararg formatArgs: Any): String {
return "Formatted string"
}
override fun getColor(resId: Int): Int {
return 0xFFFFFF
}
override fun getDrawable(resId: Int): Drawable? {
return null
}
}
- ์ด๋ ๊ฒ ๊ตฌํํ๋ฉด ViewModel์์ ๋ฆฌ์์ค๋ฅผ ์ฌ์ฉํ๋๋ผ๋ ํ ์คํธํ ๋ ์ค์ Context๋ ๋ฆฌ์์ค ํ์ผ์ ์์กดํ์ง ์๊ณ , Fake ๋๋ Mock ๋ฆฌ์์ค๋ฅผ ์ฃผ์ ํ์ฌ ํ ์คํธํ ์ ์์ต๋๋ค.
์ ๋ฆฌ
ResourceProvider์ ์ฅ์
- Context์ ์์กด์ฑ์ ์ ๊ฑฐํ์ฌ, ๋ค๋ฅธ ๊ณ์ธต์์ Context๋ฅผ ์ฐธ์กฐํ์ง ์๊ณ MVVM ํจํด์ ๊ตฌํํ ์ ์์ต๋๋ค.
- Mock์ ํ์ฉํ ํ ์คํธ์ ์ฉ์ดํ๋ฉฐ, UI ๋ฆฌ์์ค์ ์์กดํ์ง ์๊ณ ๋น์ฆ๋์ค ๋ก์ง์ ์ฝ๊ฒ ํ ์คํธํ ์ ์์ต๋๋ค.
- ๋ฆฌ์์ค์ ์ ๊ทผํ๋ ๋ก์ง์ ๋ถ๋ฆฌํ์ฌ ์ ์ง ๋ณด์์ฑ์ด ํฅ์๋๊ณ , ๋ฆฌ์์ค์ ๋ํ ์ ๊ทผ ๋ฐฉ์์ด ๋ณ๊ฒฝ๋๋๋ผ๋ ResourceProvider๋ง ์์ ํ์ฌ ํด๊ฒฐํ ์ ์์ต๋๋ค.
ResourceProvider๋ฅผ ์ฌ์ฉํ์ง ์๋๋ค๋ฉด?
- ViewModel์์ ์ง์ Context๋ฅผ ์ฌ์ฉํด์ ์๋๋ก์ด๋์ ์๋ช ์ฃผ๊ธฐ์ ์ฎ์ด๋ ๋ณต์กํ ๋ฌธ์ ๊ฐ ๋ฐ์ํ ์ ์์ต๋๋ค.
- ๋ํ Mock์ ํ์ฉํ ํ ์คํธ๊ฐ ์ด๋ ค์ฐ๋ฉฐ, ๋จ์ ํ ์คํธ์ ์ค์ ๋ฆฌ์์ค์ ์์กดํ์ฌ ํ ์คํธ ํ๊ฒฝ ๊ตฌ์ถ์ ์ด๋ ค์์ด ๋ฐ์ํ ์ ์์ต๋๋ค.
ResourceProvider๋ ์๋๋ก์ด๋ ์ฑ์์ ๋ฆฌ์์ค ์ ๊ทผ์ ์ถ์ํํ๊ณ , Context์ ๋ํ ์์กด์ฑ์ ์ค์ด๋ฉฐ ํ ์คํธ ๊ฐ๋ฅ์ฑ์ ๋์ฌ์ฃผ๋ ํจํด์ ๋๋ค. ์ด๋ฅผ ํตํด ViewModel์ด๋ ๋น์ฆ๋์ค ๋ก์ง์์ ๋ฆฌ์์ค๋ฅผ ์ฝ๊ฒ ์ฃผ์ ๋ฐ์ ์ฌ์ฉํ๊ณ , ๋ค์ํ ๋ฆฌ์์ค์ ๋ํ ๋ณ๊ฒฝ์ ์ ์ฐํ๊ฒ ์ฒ๋ฆฌํ ์ ์์ต๋๋ค.