๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
๐Ÿ’ป ๊ฐœ๋ฐœ์ž ์ด์•ผ๊ธฐ/์•ˆ๋“œ๋กœ์ด๋“œ ์‚ฝ์งˆ๊ธฐ

ViewBinding์œผ๋กœ Binding ์ฒ˜๋ฆฌํ•˜๊ธฐ. (feat. DataBinding)

by ์ •์„ ํ•œ 2024. 3. 23.
728x90
๋ฐ˜์‘ํ˜•

์ด๋ฒˆ ํฌ์ŠคํŒ…์—์„œ๋Š” ViewBinding์„ ์ข€ ๋” ๋œฏ์–ด๋ณด๊ณ  ์—ฌ๋Ÿฌ ๋ทฐ์— ์ ์šฉ๋„ ์‹œ์ผœ๋ณด๋Š” ๋‚ด์šฉ์„ ๋‹ค๋ฃจ์–ด ๋ณด๋ ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค.

  • ์‚ฌ์‹ค ํ˜„์—…์—์„œ๋‚˜ ํ•™์ƒ๋•Œ๋‚˜ ViewBinding์€ ์ตํžˆ ์จ์™”๊ณ  ์ต์ˆ™ํ•˜๊ณ  ๋‹น์—ฐํžˆ View์˜ ๋‚ด์šฉ์„ ๊ฐ€์ ธ์˜ค๊ธฐ ์œ„ํ•ด์„œ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์ด๊ธฐ ๋•Œ๋ฌธ์— ๊ธฐ์ˆ ์ ์œผ๋กœ ํƒ๊ตฌ๋ฅผ ํ•ด๋ณผ ์ƒ๊ฐ์€ ์—†์—ˆ๋Š”๋ฐ์š”.
  • ์ด๋ฒˆ์— ์—ฌ๋Ÿฌ ์ด์Šˆ๋“ค์„ ๊ฒช์œผ๋ฉด์„œ ๊ฒฝํ—˜์— ์˜์กดํ•˜๋Š” ์ฝ”๋”ฉ์ด ๊ต‰์žฅํžˆ ์œ„ํ—˜ํ•˜๊ณ  ์‹ค์ œ์ ์ธ ์—…๋ฌด ์ฒ˜๋ฆฌ ๋Šฅ๋ ฅ์„ ์ €ํ•˜์‹œํ‚ค๋Š” ๊ฒƒ์„ ๊ฒฝํ—˜ํ•˜๋ฉด์„œ ๋‹ค์‹œ ์›๋ก ์ ์ธ ๋ฌธ์ œ์— ์ง‘์ค‘ํ•˜๋Š” ์‹œ๊ฐ„์„ ๊ฐ€์ ธ๋ณด๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.
    ๊ทธ๋ž˜์„œ ์—ฌ๋Ÿฌ ๋ฌธ์„œ๋“ค์„ ๋ณด๊ณ  ์ฝ”๋“œ์—๋„ ๋…น์—ฌ๋ณด๋ฉด์„œ ์ด ๊ธ€์„ ์ž‘์„ฑํ•˜๊ณ  ์žˆ๋„ค์š”. ์—ญ์‹œ ๊ณต๋ถ€๋Š” ๋ฏธ๋ฆฌ๋ฏธ๋ฆฌ ๊ผผ๊ผผํ•˜๊ฒŒ,,,

gradle(:app) ํŒŒ์ผ์—์„œ viewBinding ํ™œ์„ฑํ™”

android {
    buildFeatures {
        viewBinding = true
    }
}

xml : result_profile.xml
xml ํŒŒ์ผ ๋ช…์—์„œ ์ƒ์„ฑ๋œ binding ํด๋ž˜์Šค์˜ ์ด๋ฆ„ : ResultProfileBinding
๋˜ํ•œ ๋ชจ๋“  Binding ํด๋ž˜์Šค์—๋Š” ์ƒ์‘ํ•˜๋Š” ๋ ˆ์ด์•„์›ƒ ํŒŒ์ผ์˜ ๋ฃจํŠธ ๋ทฐ์˜ ์ง์ ‘ ์ฐธ์กฐ๋ฅผ ์ œ๊ณตํ•˜๋Š” getRoot() (kotlin : root) ๋ฉ”์„œ๋“œ๋„ ํฌํ•จ์ž…๋‹ˆ๋‹ค.

<LinearLayout ... >
    <TextView android:id="@+id/name" />
    <ImageView android:cropToPadding="true" />
    <Button android:id="@+id/button"
        android:background="@drawable/rounded_button" />
</LinearLayout>

Activity์—์„œ View์˜ ๊ฒฐํ•ฉ์„ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•
onCreate() ๋ฉ”์„œ๋“œ์— ViewBinding์˜ ์ธ์Šคํ„ด์Šค๋ฅผ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.

  1. ์ƒ์„ฑ๋œ binding ํด๋ž˜์Šค์— ํฌํ•จ๋œ ์ •์  inflate() ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœ -> Activity์—์„œ ์‚ฌ์šฉํ•  ํด๋ž˜์Šค ์ธ์Šคํ„ด์Šค ์ƒ์„ฑ
  2. getRoot() or Kotlin ์†์„ฑ ๋ฌธ๋ฒ• .root ๋ฅผ ํ†ตํ•ด RootView๋ฅผ ์ฐธ์กฐํ•œ๋‹ค.
  3. RootView๋ฅผ setContentView()์— ์ „๋‹ฌํ•˜์—ฌ ํ™”๋ฉด์˜ ํ™œ์„ฑ ๋ทฐ๋กœ ์„ ์–ธํ•œ๋‹ค.
private lateinit var binding: ResultProfileBinding

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    binding = ResultProfileBinding.inflate(layoutInflater)
    val view = binding.root

    setContentView(view)
}

AppCompatActivity.java ๋‚ด๋ถ€์˜ setContentView() ๋ฉ”์„œ๋“œ

@Override
public void setContentView(View view) {
    initViewTreeOwners();
    getDelegate().setContentView(view);
}

Fragment ์—์„œ View ๊ฒฐํ•ฉ์„ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•
onCreateView() ๋ฉ”์„œ๋“œ์— ViewBinding์˜ ์ธ์Šคํ„ด์Šค๋ฅผ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.

  1. ์ƒ์„ฑ๋œ binding ํด๋ž˜์Šค์— ํฌํ•จ๋œ ์ •์  inflate() ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœ -> Fragment์—์„œ ์‚ฌ์šฉํ•  ํด๋ž˜์Šค ์ธ์Šคํ„ด์Šค ์ƒ์„ฑ
  2. getRoot() or Kotlin ์†์„ฑ ๋ฌธ๋ฒ• .root๋ฅผ ํ†ตํ•ด RootView๋ฅผ ์ฐธ์กฐํ•œ๋‹ค.
  3. RootView๋ฅผ onCreateView()์— ์ „๋‹ฌํ•˜์—ฌ ํ™”๋ฉด์˜ ํ™œ์„ฑ ๋ทฐ๋กœ ์„ ์–ธํ•œ๋‹ค.
private var _binding: ResultProfileBinding? = null
// This property is only valid between onCreateView and
// onDestroyView.
private val binding get() = _binding!!

override fun onCreateView(
    inflater: LayoutInflater,
    container: ViewGroup?,
    savedInstanceState: Bundle?
): View? {
    _binding = ResultProfileBinding.inflate(inflater, container, false)
    val view = binding.root
    return view
}

override fun onDestroyView() {
    super.onDestroyView()
    _binding = null
}

์—ฌ๊ธฐ๊นŒ์ง€๊ฐ€ ๊ธฐ๋ณธ์ ์œผ๋กœ Android Developer์—์„œ ์ œ๊ณตํ•˜๋Š” Guide์˜ ์ฝ”๋“œ๋“ค์ž…๋‹ˆ๋‹ค. ์ด๋Ÿฐ ๊ฒƒ์ฒ˜๋Ÿผ ViewBinding์„ ๊ตฌ์„ฑํ•  ์ˆ˜ ์žˆ๋Š”๋ฐ, ๊ทธ๋Ÿฌ๋ฉด Activity, Fragment ๋งˆ๋‹ค๋งˆ๋‹ค ๊ฐ๊ฐ์˜ ViewBinding ์ฝ”๋“œ๊ฐ€ ์ƒ๊ฒจ๋‚˜๋Š” ์ƒํ™ฉ์„ ๋งˆ์ฃผํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.
๊ทธ๋ž˜์„œ ๋ณดํ†ต์€ ์ด๋ฅผ code base ์—์„œ ๋‹ค๋ฃฐ ์ˆ˜ ์žˆ๋„๋ก ๋ถ€๋ชจ ํด๋ž˜์Šค๋ฅผ ํ•˜๋‚˜ ๋งŒ๋“ค์–ด์„œ ์‚ฌ์šฉํ•˜๊ณค ํ•ฉ๋‹ˆ๋‹ค. BaseActivity.kt , BaseFragment.kt ์ด๋Ÿฐ ์‹์œผ๋กœ ๋ฒ ์ด์Šค ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค๊ณ  ์ด ์•ˆ์—์„œ binding ๋ฐ ๊ธฐํƒ€ ๋ถ€๋ชจ ํด๋ž˜์Šค์˜ ์—ญํ• ๋กœ ๊ฐ€์ ธ๊ฐˆ ์ˆ˜ ์žˆ๋Š” ๊ฒƒ๋“ค์„ ๋ถ„๋ฆฌํ•ฉ๋‹ˆ๋‹ค.
์ด๋ ‡๊ฒŒ ์•„๋ž˜์˜ ์ฝ”๋“œ์ฒ˜๋Ÿผ BaseActivity๋ฅผ ๊ตฌํ˜„ํ•˜๊ณ  ์ด๋ฅผ ์ƒ์†๋ฐ›๋Š” ํŠน์ • Activity ์ฝ”๋“œ์—์„œ Binding ์ฒ˜๋ฆฌ๋ฅผ ํ•ด์ฃผ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.
์ด๋•Œ, setContentView()๋Š” DataBindingUtilํด๋ž˜์Šค์˜ ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.
DataBindingUtil ํด๋ž˜์Šค๋Š” Binding ํƒ€์ž…์„ ์‚ฌ์ „์— ์•Œ ์ˆ˜ ์—†์„ ๋•Œ, DataBindingUtil์„ ์‚ฌ์šฉํ•ด์„œ Binding ํด๋ž˜์Šค๋ฅผ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ๋Š” ํด๋ž˜์Šค ์ž…๋‹ˆ๋‹ค.
BaseActivity

abstract class BaseActivity<Binding : ViewDataBinding>(private val layout: Int) : AppCompatActivity() {
    protected lateinit var binding: Binding
    protected lateinit var callback: OnBackPressedCallback

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        binding = DataBindingUtil.setContentView(this, layout)
        binding.lifecycleOwner = this
    }
}
@SuppressLint("CustomSplashScreen")
@AndroidEntryPoint
class SplashActivity : BaseActivity<ActivitySplashBinding>(R.layout.activity_splash) {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
    }

    ...
}

BaseFragment

abstract class BaseFragment<Binding : ViewDataBinding>(private val layout: Int) : Fragment() {
    protected lateinit var binding: Binding

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        binding = DataBindingUtil.inflate(inflater, layout, container, false)
        binding.lifecycleOwner = viewLifecycleOwner
        return binding.root
    }
    ....
}
@AndroidEntryPoint
class MainFragment : BaseFragment<FragmentMainBinding>(R.layout.fragment_main) {

    ....

}

๊ทผ๋ฐ ์‚ฌ์‹ค ์ด๋ ‡๊ฒŒ ๋˜๋ฉด ViewBinding ๋ณด๋‹ค๋Š” DataBinding์œผ๋กœ ๊ตฌํ˜„ํ•˜๋Š” ๋ฐฉ๋ฒ•์ด ๋˜๊ฒ ๋„ค์š”. ์ด๋ ‡๊ฒŒ DataBinding์„ ์‚ฌ์šฉํ•  ๋•Œ์—๋Š” xml ์ฝ”๋“œ ๋‚ด ์ตœ์ƒ์œ„ ํƒœ๊ทธ๋ฅผ <layout> </layout>์œผ๋กœ ์ง€์ •ํ•ด ์ฃผ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋ฉด ViewBinding๊ณผ DataBinding์ด ๋‹ค๋ฅธ ๊ฑฐ๋ƒ,,๋ผ๊ณ  ํ•˜๊ธฐ์—๋Š” viewBinding์ด DataBinding์˜ ๋ถ€๋ถ„์ง‘ํ•ฉ์ด๋ผ ์ด๊ฑธ ๋”ฐ์ง€๋Š” ์˜๋ฏธ๊ฐ€ ์žˆ์„๊นŒ ์‹ถ๊ธฐ๋„ ํ•ฉ๋‹ˆ๋‹ค.
์•ฝ๊ฐ„ View ๊ฐ์ฒดํ™” ๋ฐฉ๋ฒ• ์ค‘ findViewById()๋ฅผ ์“ฐ์ง€ ์•Š๊ธฐ ์œ„ํ•ด์„œ๋Š” ViewBinding์„ ๊ถŒ์žฅํ•˜๋Š” ๋“ฏํ•˜๊ณ  ์ข€ ๋” ๋™์ ์œผ๋กœ ์‚ฌ์šฉํ•˜๊ณ  ๋‹จ์ˆœํžˆ View ๋ฟ๋งŒ์ด ์•„๋‹Œ ๊ธฐ๋Šฅ์  ์‚ฌ์šฉ์„ ์œ„ํ•ด์„œ๋Š” DataBinding์„ ์ด๋Ÿฐ ๋А๋‚Œ์œผ๋กœ ๊ถŒ์žฅํ•˜๋Š” ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.
์ €๋Š” ์‹ค๋ฌด ํ”„๋กœ์ ํŠธ์—์„œ DataBinding, ViewBinding์„ ํ˜ผ์šฉํ•ด์„œ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ๋Š”๋ฐ์š”. ํ˜ผ์šฉ ์ž์ฒด์—๋Š” ๋ฌธ์ œ๊ฐ€ ์—†์ง€๋งŒ ์ข€ ๋” ๋‚˜์€ ๋ฐฉ๋ฒ•์ด ์žˆ๋‹ค๋ฉด ๊ฐœ์„ ์„ ํ•ด๋ด„์งํ•˜๊ธฐ๋„ ํ•œ ๊ฒƒ ๊ฐ™๋„ค์š”. ํ ๐Ÿ˜•

728x90
๋ฐ˜์‘ํ˜•