국비교육(22-23)

72일차(3)/Android App(19) : View Binding

서리/Seori 2023. 1. 19. 00:36

72일차(3)/Android App(19) : View Binding

 

step08viewbinding 모듈 생성

 

MainActivity

package com.example.step08viewbinding;

import android.os.Bundle;
import android.view.View;

import androidx.appcompat.app.AppCompatActivity;

import com.example.step08viewbinding.databinding.ActivityMainBinding;

/*
    view binding 사용하는 방법

    1. build.gradle 파일에 설정(추가)

    buildFeatures {
        viewBinding = true
    }

    2. build.gradle 파일의 우상단 sync now 버튼 눌러서 실제로 반영되도록 한다.

    3. layout xml 문서의 이름을 확인해서 자동으로 만드는 클래스명을 예측한다.

    예를들어 activity_main.xml 문서이면 ActivityMainBinding 클래스
    예를들어 activity_sub.xml 문서이면 ActivitySubBinding 클래스...
 */
public class MainActivity extends AppCompatActivity implements View.OnClickListener{
    //ActivityMainBinding 객체의 참조값을 담을 필드
    ActivityMainBinding binding;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        //setContentView(R.layout.activity_main); //바인딩을 사용할때는 이렇게 사용하지 않는다.

        //activity_main.xml 문서에 전개된 EditText, Button, TextView의 참조값 얻어오는 방법1
        /*EditText editText=findViewById(R.id.editText);
        Button button=findViewById(R.id.button);
        TextView textView=findViewById(R.id.textView);
        */

        //activity_main.xml 문서에 전개된 EditText, Button, TextView의 참조값 얻어오는 방법2
        /*ActivityMainBinding binding=ActivityMainBinding.inflate(getLayoutInflater());
        EditText editText=binding.editText;
        Button button=binding.button;
        TextView textView=binding.textView;
        */
        /*
            예를 들어 EditText에 문자열을 입력하고 버튼을 누르면 입력한 문자열이
            TextView로 이동하도록 프로그래밍 한다면 아래와 같은 코딩이 된다.
         */
        //바인딩 객체의 참조값을 얻어와서 필드에 저장
        binding=ActivityMainBinding.inflate(getLayoutInflater());
        //바인딩 객체가 리턴해주는 View를 이용해서 화면 구성하기
        setContentView(binding.getRoot());

        //버튼에 리스너 등록하기
        binding.button.setOnClickListener(this);
    }

    @Override
    public void onClick(View view) {
        //EditText 객체에 입력한 문자열 읽어오기
        String msg=binding.editText.getText().toString();
        //TextView에 출력하기
        binding.textView.setText(msg);
    }
}

 

activity_main.xml

<?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/editText"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="35dp"
        android:ems="10"
        android:inputType="textPersonName"
        android:minHeight="48dp"
        android:text="Name"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="35dp"
        android:text="Button"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/editText" />

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginStart="18dp"
        android:layout_marginTop="114dp"
        android:text="TextView"
        app:layout_constraintStart_toStartOf="@+id/button"
        app:layout_constraintTop_toBottomOf="@+id/button" />
</androidx.constraintlayout.widget.ConstraintLayout>

 

- plaintext, 버튼, textview 추가

 

- UI의 참조값을 그냥 findViewById() 로 찾아오는 방법을 지금까지 사용했는데

 이게 조금... 느리다고 한다.. 느낄 정도는 아니지만..?

 

- 다른방법을 사용해볼 예정! View binding 사용방법

 

- build.gradle 파일로 들어가기

- Maven의 pom.xml과 비슷한 파일. 설정/의존 디펜던시를 관리한다.

 

- 내용 적고 우상단 Sync now 버튼으로 싱크시키기

- 저 버튼을 누르거나 아니면 File-Sync Project 하면 된다.

 

buildFeatures {
    viewBinding = true
}

- 이 내용을 위 이미지의 위치에 넣어준다.

 

- 그러면 자동으로 ActivityMainBinding 이라는 클래스가 만들어진다.

 

- 이렇게 ActivityMainBinding 클래스가 자동으로 만들어진 것을 확인할 수 있다.

- 이것을 ViewBinding 타입으로 받는다!

 

- 각각의 필드에 이렇게 각 요소의 참조값이 들어가있다.

- 좀더 안전하게 UI의 참조값을 얻어오는 방법이다. 안드로이드에서는 이것을 권장하는 쪽!

- 어쨌든 둘다 알고있어야 한다.ㅎㅎ

 

 

- 버튼에 리스너등록 → editText 참조값으로 값읽어오기 textView에 넣어주기 

 

- binding 을 필드로 만들어 두었으므로 그냥 점 찍어서 가져오기

 

- findViewById로 참조값을 얻어와서 필드에 넣는 대신 이렇게 쓸 수 있다.

 

- 아래에서 editText, textView 도 그대로 binding에 점찍어서 접근한다.

 

- run했을때 gradle 설정때문에 오류가 발생한다면...

저번에 했던대로 compileSdk를 32 -> 33 으로 수정하기!

 

- 이 방식으로 참조값을 얻어올 때는 setContentView는 지운다.

 

//바인딩 객체의 참조값을 얻어와서 필드에 저장
binding=ActivityMainBinding.inflate(getLayoutInflater());
//바인딩 객체가 리턴해주는 View를 이용해서 화면 구성하기
setContentView(binding.getRoot());

- 이렇게 필드에 값을 저장한 후, getRoot() 메소드로 화면을 구성한다.

 


 

- new-fragment로 빈 프래그먼트 추가!

 

BlankFragment

package com.example.step08viewbinding;

import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import androidx.fragment.app.Fragment;

import com.example.step08viewbinding.databinding.FragmentBlankBinding;

/**
 * A simple {@link Fragment} subclass.
 * Use the {@link BlankFragment#newInstance} factory method to
 * create an instance of this fragment.
 */
public class BlankFragment extends Fragment {


    private static final String ARG_PARAM1 = "param1";
    private static final String ARG_PARAM2 = "param2";


    private String mParam1;
    private String mParam2;

    public BlankFragment() {

    }


    public static BlankFragment newInstance(String param1, String param2) {
        BlankFragment fragment = new BlankFragment();
        Bundle args = new Bundle();
        args.putString(ARG_PARAM1, param1);
        args.putString(ARG_PARAM2, param2);
        fragment.setArguments(args);
        return fragment;
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (getArguments() != null) {
            mParam1 = getArguments().getString(ARG_PARAM1);
            mParam2 = getArguments().getString(ARG_PARAM2);
        }
    }

    //바인딩 객체를 저장할 필드
    FragmentBlankBinding binding;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // view binding을 이용하려면 아래와 같이 코딩해야 한다.

        //fragment_black.xml문서 => FragmentBlankBinding 클래스
        binding=FragmentBlankBinding.inflate(inflater,container,false);
        View view=binding.getRoot();

        //만일 fragment_blank.xml 문서에 myTextView라는 아이디를 가지고있는 TextView의 참조값이 필요하다면
        TextView a= binding.myTextView; //이렇게 참조하면 된다.

        return view;
    }

    // fragment가 레이아웃으로 가지고있는 뷰가 파괴될때 호출되는 메소드
    @Override
    public void onDestroyView() {
        super.onDestroyView();
        //FragmentBlankBinding 객체의 참조를 해제해서 메모리를 효율적으로 사용하도록 한다.
        binding=null;
        //프래그먼트보다 뷰가 더 오래 살아남기 때문에 프래그먼트는 사용되지 않는데
        //뷰만 메모리에 남아있는 것을 방지하는 효과가 된다.
    }
}

 

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".BlankFragment">

    <!-- TODO: Update blank fragment layout -->
    <TextView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:text="hello"
        android:id="@+id/myTextView" />

</FrameLayout>

 

- 이 xml문서를 전개해서 view를 만들어서 view를 리턴해야하는데,

  뷰 바인딩을 사용하면 방법이 좀 달라진다.

 

 

- fragment_blank.xml 문서 => FragmentBlankBinding 클래스

- xml 문서 하나당 이 클래스가 자동으로 generate 된다.

 

- inflate를 사용하는 방식. 위, 아래의 작성방법을 비교하기!

 

- 만약 저 xml문서안에 id가 부여된 UI가 있다면 binding 을 통해서 접근할 수 있다.

→ 필드에 값을 저장할 필요가 있다!

 

- 마지막에 onDestroyView() 메소드로 binding을 해제해주어야 한다. 메모리를 효율적으로 사용하기 위해!

- 프래그먼트보다 뷰가 더 오래 살아남기 때문에 프래그먼트는 사용되지 않는데,
  View 만 메모리에 남아있는 것을 방지하는 효과가 된다.

 

- 이렇게 binding을 통해 UI의 참조값을 가져올 수 있다.

 

- 이것은 fragment_blank.xml 에 들어있는 textView인데

 만약 이 UI에 접근하고자 한다면 이런식으로 접근하면 된다.

 

- 이전에 참조값을 얻어오던 방식과 똑같이 작동한다.