ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Android] ViewBinding์ด๋ž€?
    Android 2022. 3. 20. 03:18
    ๋ฐ˜์‘ํ˜•

    View Binding?

      Activity, Fragment์˜ UI๋ฅผ ๋ณ€๊ฒฝํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” XML ํŒŒ์ผ์„ ์ธํ”Œ๋ ˆ์ด์…˜ ํ›„ ๊ฐ View๋“ค์„ findViewById๋ฅผ ํ†ตํ•ด ์ฐธ์กฐ๋ฅผ ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค. ๊ฐ„๋‹จํ•œ UI์ผ ๊ฒฝ์šฐ์—๋Š” ํฌ๊ฒŒ ์ƒ๊ด€์—†์ง€๋งŒ, ๋ณต์žกํ•œ UI์ผ์ˆ˜๋ก ๋ณด์ผ๋Ÿฌ ํ”Œ๋ ˆ์ดํŠธ ์ฝ”๋“œ๋ฅผ ์–‘์‚ฐํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ๋ฐฉ์ง€ํ•˜๊ณ  ์‰ฝ๊ฒŒ View์™€ ์ƒํ˜ธ์ž‘์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ ๋‚˜์˜จ ๊ฒƒ์ด DataBinding๊ณผ ViewBinding์ž…๋‹ˆ๋‹ค. ์ด๋ฒˆ ๊ธ€์—์„œ๋Š” ViewBinding์— ๋Œ€ํ•ด์„œ๋งŒ ๋จผ์ € ์„ค๋ช…ํ•˜๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. 

     

     

    View Binding ์„ค์ •

       View Binding์€ ๋ชจ๋“ˆ๋ณ„๋กœ ์„ค์ •ํ•˜๊ธฐ์— build.gradle(Module) ์— ์•„๋ž˜์™€ ๊ฐ™์ด ์„ค์ •ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

    android {
            ...
            viewBinding {
                enabled = true
            }
        }

     

      ๋ชจ๋“ˆ์—์„œ ์„ค์ •๋œ View Binding์€ ๋ชจ๋“ˆ ๋‚ด์— ์žˆ๋Š” ๋ชจ๋“  ๋ ˆ์ด์•„์›ƒ ํŒŒ์ผ๋“ค์— ํ•ด๋‹นํ•˜๋Š” ๋ฐ”์ธ๋”ฉ ํด๋ž˜์Šค๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. ๋˜ํ•œ, ๋ฐ”์ธ๋”ฉ ํด๋ž˜์Šค ๋‚ด์— ๋ ˆ์ด์•„์›ƒ์— ํฌํ•จ๋œ ๋ทฐ๋“ค์— ๋Œ€ํ•œ ์ฐธ์กฐ๊ฐ€ ๊ฐ๊ฐ ์ •์˜๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค.

     

    <LinearLayout
                ...
                tools:viewBindingIgnore="true" >
            ...
        </LinearLayout>

      ๋ชจ๋“ˆ ๋‚ด์˜ ๋ชจ๋“  ๋ ˆ์ด์•„์›ƒ ํŒŒ์ผ๋“ค์„ ์ž๋™์œผ๋กœ ๋ฐ”์ธ๋”ฉ ํด๋ž˜์Šค๋ฅผ ์ƒ์„ฑ๋˜๋Š” ๊ฒƒ์„ ๋ฌด์‹œํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋ฃจํŠธ๋ทฐ์— tools:viewBindingIgnore = "true" ๋ฅผ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

     

     

    View Binding ์‚ฌ์šฉ

    <?xml version="1.0" encoding="utf-8"?>
    <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">
    
        <EditText
            android:id="@+id/searchEditText"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:inputType="text"
            android:lines="1"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />
    
        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/bookRecyclerView"
            android:layout_width="0dp"
            android:layout_height="0dp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@id/searchEditText" />
    
        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/historyRecyclerView"
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:background="@color/white"
            android:visibility="gone"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@id/searchEditText" />
    
    </androidx.constraintlayout.widget.ConstraintLayout>

      ๋‹ค์Œ๊ณผ ๊ฐ™์ด ๋ ˆ์ด์•„์›ƒ ํŒŒ์ผ์ด ์žˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•ฉ๋‹ˆ๋‹ค. ๋ฃจํŠธ ๋ทฐ๋Š” ConstraintLayout์ด๊ณ  ๋‚ด๋ถ€์— EditText 1๊ฐœ์™€ RecyclerView๊ฐ€ 2๊ฐœ ์กด์žฌํ•ฉ๋‹ˆ๋‹ค. ์œ„์—์„œ ์–ธ๊ธ‰ํ–ˆ๋“ฏ์ด View Binding์ด ์„ค์ •๋˜์–ด ์žˆ์œผ๋ฉด ๋ ˆ์ด์•„์›ƒ์— ์ƒ์‘ํ•˜๋Š” ๋ฐ”์ธ๋”ฉ ํด๋ž˜์Šค๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. ๋ฐ”์ธ๋”ฉ ํด๋ž˜์Šค์˜ ์ด๋ฆ„์€ XML ํŒŒ์ผ์˜ ์ด๋ฆ„์œผ๋กœ Camel Case์œผ๋กœ ๋ณ€ํ™˜ํ•˜๊ณ  "Binding" ์„ ์ถ”๊ฐ€ํ•˜์—ฌ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. 

     

      ์‹ค์ œ ๋ฐ”์ธ๋”ฉ ํด๋ž˜์Šค๋ฅผ ๋ณด๊ณ  ์‹ถ๋‹ค๋ฉด ์•ˆ๋“œ๋กœ์ด๋“œ ์ŠคํŠœ๋””์˜ค Android ๋ทฐ์—์„œ Project๋กœ ๋ณ€๊ฒฝ ํ›„ app > build > ... > databinding ํด๋” ์•„๋ž˜์— ์ƒ์„ฑ๋˜๋Š” ๊ฒƒ์„ ํ™•์ธํ•˜์‹ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

     

     

    Activity์—์„œ View Binding ์‚ฌ์šฉ

    class MainActivity : AppCompatActivity() {
    
        private lateinit var binding: ActivityMainBinding
    
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            binding = ActivityMainBinding.inflate(layoutInflater)
            setContentView(binding.root)
        }

      ๋ ˆ์ด์•„์›ƒ ํŒŒ์ผ์˜ ์ด๋ฆ„์ด acitivity_main.xml์ด๊ธฐ์— ๋ฐ”์ธ๋”ฉ ํด๋ž˜์Šค๊ฐ€ ActivityMainBinding์œผ๋กœ ์ƒ์„ฑ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ActivityMainBinding์˜ Static ๋ฉ”์†Œ๋“œ์ธ inflate ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜์—ฌ Binding ํด๋ž˜์Šค๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. ์ดํ›„ setContentView์— ๋ฃจํŠธ ๋ทฐ๋ฅผ ์ „๋‹ฌํ•˜์—ฌ ๋ ˆ์ด์•„์›ƒ์˜ ํ™”๋ฉด์„ ๋‚˜ํƒ€๋ƒ…๋‹ˆ๋‹ค.

     

     

    // Generated by view binder compiler. Do not edit!
    package ows.kotlinstudy.bookreview.databinding;
    
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.EditText;
    import androidx.annotation.NonNull;
    import androidx.annotation.Nullable;
    import androidx.constraintlayout.widget.ConstraintLayout;
    import androidx.recyclerview.widget.RecyclerView;
    import androidx.viewbinding.ViewBinding;
    import java.lang.NullPointerException;
    import java.lang.Override;
    import java.lang.String;
    import ows.kotlinstudy.bookreview.R;
    
    public final class ActivityMainBinding implements ViewBinding {
      @NonNull
      private final ConstraintLayout rootView;
    
      @NonNull
      public final RecyclerView bookRecyclerView;
    
      @NonNull
      public final RecyclerView historyRecyclerView;
    
      @NonNull
      public final EditText searchEditText;
    
      private ActivityMainBinding(@NonNull ConstraintLayout rootView,
          @NonNull RecyclerView bookRecyclerView, @NonNull RecyclerView historyRecyclerView,
          @NonNull EditText searchEditText) {
        this.rootView = rootView;
        this.bookRecyclerView = bookRecyclerView;
        this.historyRecyclerView = historyRecyclerView;
        this.searchEditText = searchEditText;
      }
    
      @Override
      @NonNull
      public ConstraintLayout getRoot() {
        return rootView;
      }
    
      @NonNull
      public static ActivityMainBinding inflate(@NonNull LayoutInflater inflater) {
        return inflate(inflater, null, false);
      }
    
      @NonNull
      public static ActivityMainBinding inflate(@NonNull LayoutInflater inflater,
          @Nullable ViewGroup parent, boolean attachToParent) {
        View root = inflater.inflate(R.layout.activity_main, parent, false);
        if (attachToParent) {
          parent.addView(root);
        }
        return bind(root);
      }
    
      @NonNull
      public static ActivityMainBinding bind(@NonNull View rootView) {
        // The body of this method is generated in a way you would not otherwise write.
        // This is done to optimize the compiled bytecode for size and performance.
        int id;
        missingId: {
          id = R.id.bookRecyclerView;
          RecyclerView bookRecyclerView = rootView.findViewById(id);
          if (bookRecyclerView == null) {
            break missingId;
          }
    
          id = R.id.historyRecyclerView;
          RecyclerView historyRecyclerView = rootView.findViewById(id);
          if (historyRecyclerView == null) {
            break missingId;
          }
    
          id = R.id.searchEditText;
          EditText searchEditText = rootView.findViewById(id);
          if (searchEditText == null) {
            break missingId;
          }
    
          return new ActivityMainBinding((ConstraintLayout) rootView, bookRecyclerView,
              historyRecyclerView, searchEditText);
        }
        String missingId = rootView.getResources().getResourceName(id);
        throw new NullPointerException("Missing required view with ID: ".concat(missingId));
      }
    }

     

      ์œ„์˜ ์ฝ”๋“œ๋Š” ์‹ค์ œ๋กœ ์ƒ์„ฑ๋œ ActivityMainBinding ํด๋ž˜์Šค๋กœ ์†์„ฑ์— rootView ์ด์™ธ์—๋„ rootView์— ํฌํ•จ๋œ ๋ชจ๋“  ๋ทฐ๋“ค์— ๋Œ€ํ•œ ์ฐธ์กฐ๊ฐ€ ์กด์žฌํ•ฉ๋‹ˆ๋‹ค. ๋‚ด๋ถ€์ ์œผ๋กœ ActivityMainBinding ํด๋ž˜์Šค๊ฐ€ ์ƒ์„ฑ๋˜๋Š” ํ๋ฆ„์„ ์‚ดํŽด๋ณด๋Š” ๊ฒƒ๋„ ์ข‹์Šต๋‹ˆ๋‹ค.

     

    1. inflate(LayoutInflater) 
    2. inflate(LayoutInflater, ViewGroup, boolean) 
    3. bind(View)

     Activity ๊ฐ™์€ ๊ฒฝ์šฐ๋Š” parent๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š๊ธฐ์— inflate(LayoutInflater)๊ฐ€ ํ˜ธ์ถœ๋˜์ง€๋งŒ, Fragment ๋‚˜ RecyclerView์˜ Item์— ํ•ด๋‹นํ•˜๋Š” View๋“ค์€ inflate(LayoutInflater, ViewGroup, boolean)์ด ๋ฐ”๋กœ ํ˜ธ์ถœ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ธํ”Œ๋ ˆ์ด์…˜์„ ํ†ตํ•ด rootView๋ฅผ ์–ป๋Š”๋‹ค๋ฉด bind ๋ฉ”์†Œ๋“œ์— rootView๋ฅผ ๋Œ€์ž…ํ•˜์—ฌ ๋ชจ๋“  ๋ทฐ์— ๋Œ€ํ•œ ์ฐธ์กฐ๋ฅผ findViewById๋ฅผ ํ†ตํ•ด ์–ป์–ด์˜ค๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ๋ฆฌํ„ด ๊ฐ’์œผ๋กœ ActivityMainBinding์„ ๋ฐ˜ํ™˜ํ•˜๊ฒŒ ๋˜๊ณ  ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ์ฐธ์กฐํ•œ ๋ทฐ๋“ค์„ ๋ชจ๋‘ ๋Œ€์ž…ํ•˜์—ฌ ์†์„ฑ์œผ๋กœ ์กด์žฌํ•˜๋Š” ๋ชจ๋“  ๋ทฐ๋“ค์„ ์„ธํŒ…๊นŒ์ง€ ๋งˆ๋ฌด๋ฆฌํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ์ด๋Ÿฐ ๋กœ์ง์„ ํ†ตํ•ด์„œ ActivityMainBinding.inflate ๋ฉ”์†Œ๋“œ๋งŒ ํ˜ธ์ถœํ•˜๋”๋ผ๋„ ๋ชจ๋“  ๋ทฐ๋“ค์„ ๋ฐ”์ธ๋”ฉ ํด๋ž˜์Šค๋กœ ์ฐธ์กฐ๋ฅผ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ฐธ ์‰ฝ์ฃ ?~

     

     

    Fragment View Binding ์‚ฌ์šฉ

      Activity์—์„œ๋Š” View Binding์„ ์‚ฌ์šฉํ•  ๋•Œ ํฐ ์ฃผ์˜์‚ฌํ•ญ์€ ์—†์ง€๋งŒ Fragment์—์„œ View Binding์„ ์‚ฌ์šฉํ•  ๋•Œ ์ฃผ์˜ํ•  ์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

        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
        }
        

      onCreateView์—์„œ View Binding ํด๋ž˜์Šค๋ฅผ ์ƒ์„ฑํ•˜๊ณ  onDestroyView์—์„œ๋Š” ๊ผญ View Binding์„ null ์ฒ˜๋ฆฌ ํ•ด์ฃผ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. Fragment์˜ ์ƒ๋ช…์ฃผ๊ธฐ๋กœ ๋ณด๋ฉด onDestory ๋ฉ”์†Œ๋“œ๊ฐ€ onDestoryView ๋‹ค์Œ์— ํ˜ธ์ถœ๋˜๊ธฐ์— View๋ณด๋‹ค ์˜ค๋ž˜ ์ง€์†๋œ๋‹ค๊ณ  ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ž˜์„œ Fragment๊ฐ€ ์ข…๋ฃŒ๋˜๊ธฐ ์ „์— View๋ฅผ null์ฒ˜๋ฆฌ ํ•ด์„œ GC๊ฐ€ ์ˆ˜์ง‘ํ•ด๊ฐˆ ์ˆ˜ ์žˆ๋„๋ก ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค. ๋งŒ์ผ null์ฒ˜๋ฆฌ๋ฅผ ํ•˜์ง€ ์•Š์„ ๊ฒฝ์šฐ์— Fragment๋Š” ๋ฐ”์ธ๋”ฉ ํด๋ž˜์Šค์— ๊ฐ•ํ•œ ์ฐธ์กฐ ๋˜๊ณ  ์žˆ์–ด์„œ Fragment๊ฐ€ ์ข…๋ฃŒ๋˜๋”๋ผ๋„ ๋ฐ”์ธ๋”ฉ ํด๋ž˜์Šค๋กœ ์ธํ•ด GC๊ฐ€ ์ˆ˜์ง‘ํ•˜์ง€ ์•Š๋Š” ํ˜„์ƒ์ด ๋‚˜ํƒ€๋‚  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ฆ‰ ๋ฉ”๋ชจ๋ฆฌ ๋ˆ„์ˆ˜๋กœ ์ด์–ด์ง€๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ์ด ๋ถ€๋ถ„์ด ์ดํ•ด๊ฐ€ ๊ฐ€์ง€ ์•Š๋Š”๋‹ค๋ฉด Stronge Reference, Week Reference์— ๋Œ€ํ•ด์„œ ๊ณต๋ถ€ํ•ด๋ณด์…”๋„ ์ข‹์„ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

    ๋ฐ˜์‘ํ˜•

     

    findViewById์™€์˜ ์ฐจ์ด์ 

    Null ์•ˆ์ „์„ฑ 

      ๋ฐ”์ธ๋”ฉ ํด๋ž˜์Šค๊ฐ€ ์ง์ ‘ ๋ทฐ๋“ค์„ ์ฐธ์กฐํ•˜๊ธฐ์— ์ž˜๋ชป๋œ id๋กœ ์ธํ•œ NullPointerException๊ณผ ํœด๋จผ์—๋Ÿฌ๋ฅผ ๋ฐฉ์ง€ํ•ฉ๋‹ˆ๋‹ค.

     

    Type ์•ˆ์ •์„ฑ

      ์œ„์˜ ์žฅ์ ๊ณผ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ๋ฐ”์ธ๋”ฉ ํด๋ž˜์Šค๊ฐ€ XML ํŒŒ์ผ์— ์ •์˜๋œ ๋ทฐ๋“ค์„ ๊ฐ€์ง€๊ณ  ์ฐธ์กฐ๋ฅผ ํ•˜๊ธฐ์— ํด๋ž˜์Šค ๋ณ€ํ™˜๊ณผ ๊ฐ™์€ ์—๋Ÿฌ๋ฅผ ๋ฐฉ์ง€ํ•ฉ๋‹ˆ๋‹ค.

     

     

    DataBinding๊ณผ์˜ ์ฐจ์ด์ 

    ๋” ๋น ๋ฅธ ์ปดํŒŒ์ผ

      @BindingAdapter์™€ ๊ฐ™์€ ์–ด๋…ธํ…Œ์ด์…˜ ํ”„๋กœ์„ธ์‹ฑ์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ธฐ์— ์ปดํŒŒ์ผ ์‹œ๊ฐ„์ด ์งง์Šต๋‹ˆ๋‹ค.

     

    ํŽธ๋ฆฌํ•œ ์‚ฌ์šฉ์„ฑ 

      DataBinding์€ XML ํŒŒ์ผ์— <layout> ํƒœ๊ทธ๋ฅผ ์ถ”๊ฐ€ํ•ด์•ผ๋งŒ ๋ฐ”์ธ๋”ฉ ํด๋ž˜์Šค๋ฅผ ์ƒ์„ฑํ•˜๋Š”๋ฐ ๋ฐ˜ํ•ด ViewBinding์€ ๋ชจ๋“  ๋ชจ๋“ˆ ๋‚ด์— ์กด์žฌํ•˜๋Š” ๋ ˆ์ด์•„์›ƒ์„ ์ž๋™์œผ๋กœ ์ƒ์„ฑํ•˜์—ฌ ํŽธ๋ฆฌํ•ฉ๋‹ˆ๋‹ค.

     

    ๋ ˆ์ด์•„์›ƒ ํ‘œํ˜„์‹

      DataBinding์€ ๋ ˆ์ด์•„์›ƒ ๋‚ด์— ์ด๋ฒคํŠธ๋ฅผ ์„ค์ •ํ•˜๊ฑฐ๋‚˜ ๊ฐ’์„ ๋Œ€์ž…ํ•  ์ˆ˜ ์žˆ์–ด ์„ ์–ธํ˜• ํ”„๋กœ๊ทธ๋ž˜๋ฐ์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ViewBinding์€ ์ง€์›ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

     

    ์–‘๋ฐฉํ–ฅ ๋ฐ์ดํ„ฐ ๊ฒฐํ•ฉ

      ViewBinding์€ ์ฝ”๋“œ ๋‚ด์—์„œ ๋ ˆ์ด์•„์›ƒ์„ ์ฐธ์กฐํ–ˆ๋‹ค๋ฉด, DataBinding์€ ๋ ˆ์ด์•„์›ƒ์—์„œ ์ฝ”๋“œ ๋‚ด์˜ ๋ณ€์ˆ˜๋ฅผ ์ฐธ์กฐํ•˜์—ฌ ๊ฐ’์„ ๋ณ€๊ฒฝํ•˜๊ฑฐ๋‚˜ UI๋ฅผ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ์–ด์„œ ์–‘๋ฐฉํ–ฅ์œผ๋กœ ์ƒํ˜ธ์ž‘์šฉ์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

     

     

     

     

    ์ฐธ๊ณ 

     

    ๋ทฐ ๊ฒฐํ•ฉ  |  Android ๊ฐœ๋ฐœ์ž  |  Android Developers

    ๋ทฐ ๊ฒฐํ•ฉ ๋ทฐ ๊ฒฐํ•ฉ ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•˜๋ฉด ๋ทฐ์™€ ์ƒํ˜ธ์ž‘์šฉํ•˜๋Š” ์ฝ”๋“œ๋ฅผ ์‰ฝ๊ฒŒ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ชจ๋“ˆ์—์„œ ์‚ฌ์šฉ ์„ค์ •๋œ ๋ทฐ ๊ฒฐํ•ฉ์€ ๋ชจ๋“ˆ์— ์žˆ๋Š” ๊ฐ XML ๋ ˆ์ด์•„์›ƒ ํŒŒ์ผ์˜ ๊ฒฐํ•ฉ ํด๋ž˜์Šค๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. ๋ฐ”์ธ๋”ฉ

    developer.android.com

     

     

    ๋ฐ˜์‘ํ˜•
Designed by Tistory.