data binding 공부해보자!

Assist·2023년 5월 28일
0

매일 아침 일어나면 오늘은 무엇을 공부해서 글을 쓸까 고민을 합니다.

와중에 멘토님이 databinding을 써보세요! 라고 해서 한번 공부해 보려고 합니다.
참고로 전 진짜 코딩에서 보수적이었습니다. 변화를 정말 싫어하지요
(F-lab 덕분에정말 큰일난걸 알고 고치고 공부하고 있지요)

Data binding 이 뭔데?

Data binding이란?
제가 대학생때 android을 배울때는
findViewById을 써서 R.id.imageView 이런식 으로 코드를 작성해서 변수에
대입 했던것으로 기억합니다.

예를 들어

TextView textView = findViewById(R.id.textView);
textView.setText("Hello world");

참 추억입니다. 이런식으로 findViewById 을 사용하면 android에서 뭐가 문제냐?
일단 해당 id가 있는지 모든 view을 찾아다닙니다.
이러면 android에서 성능 문제도 당연이 생기겠지요?

그래서 저는 view binding을 사용하지요.
view binding은 해당 view에서만 id을 찾으니까요

그래서 data binidng이 뭔데??

쉽게 말해서 xml에 변수를 집어넣고 그걸 쓴는겁니다.

왜 쓰냐

xml에 변수를 집어넣음으로 기존에 제가 쓰던

binding.txtview.text = "helloWorld" 
binding.txtview2.text = "helloWorld" 

이런걸

binding.argText = "helloWorld"

이 한줄로 사용하면 txtview , txtView2 가 argText을 사용한다면
더이상 코드를 작성할 필요가 없겠지요

이런식으로 코드 간결성을 높이는 활동입니다.

자 그럼 적용 해볼까요?

Data binding을 적용해보자!

일단 build.gradle(Moudle) 으로 가서

    dataBinding{
        enabled true
    }

이것만 해주면 사용준비 끝입니다.

자 그럼 제가 이전에 사용하던 Naver 검색 api 을 통해 한번 적용해보겠습니다.

<layout>
 //data binding을 위한 변수들 
    <data>
        <variable
            name="argTitle"
            type="java.lang.String" />
        <variable
            name="argLink"
            type="java.lang.String" />
    </data>

    <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools">

        <ImageView
            android:id="@+id/img_book"
            android:layout_width="100dp"
            android:layout_height="100dp"
            tools:background="@drawable/ic_book_test"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"/>
		
        <TextView
            android:id="@+id/txt_title"
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:text="@{argTitle}" // 변수 적용 
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintStart_toEndOf="@id/img_book"
            app:layout_constraintBottom_toTopOf="@id/txt_link"
            app:layout_constraintEnd_toEndOf="parent"

            android:gravity="center"
            tools:text="제목 : 안드로이드 어플 백과 (안드로이드 유저가 반드시 챙겨야 할 머스트해브 어플 해부)"/>

        <TextView
            android:id="@+id/txt_link"
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:text="@{argLink}"// 변수 적용 
            android:gravity="center"
            app:layout_constraintTop_toBottomOf="@id/txt_title"

            app:layout_constraintStart_toEndOf="@id/img_book"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintBottom_toBottomOf="parent"
            tools:text="www.naver.com"/>



    </androidx.constraintlayout.widget.ConstraintLayout>
</layout>

저기 보면

   <data>
        <variable
            name="argTitle"
            type="java.lang.String" />
        <variable
            name="argLink"
            type="java.lang.String" />
    </data>

이게 제가 사용할 변수 들입니다.

참고로 이 xml은 recyclerview adapter 이기 때문에
binding이 아닌 holder가 붙습니다.
(다른 분들은 다르게 사용할수 있습니다 꼭 holder을 붙이지는 않습니다)

자 그럼 adapter 을 보겠습니다

class BookAdapter (private val context : Context) : RecyclerView.Adapter<BookAdapter.ViewHolder>() {
    var data = ArrayList<Book>()
    private var onClickListener : OnItemClickListener ?= null
    inner class  ViewHolder( val binding : AdapterBookBinding) : RecyclerView.ViewHolder(binding.root)

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        val binding = AdapterBookBinding.inflate(LayoutInflater.from(parent.context) , parent ,false )
        return ViewHolder(binding)
    }

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
    	//data binding 
        holder.binding.argTitle = data[position].title
        holder.binding.argLink = data[position].link
        
//기존 사용 코드 
//        holder.binding.txtTitle.text = data[position].title

        Glide.with(context)
            .load(data[position].image)
            .into(holder.binding.imgBook)
        //recyclerview Click Listener
        holder.binding.txtLink.setOnClickListener {
            onClickListener!!.onClickListener(data[position].link)
        }
    }

    override fun getItemCount(): Int {
       return data.size
    }

    //interface 정의
    fun setOnClickListener(clickListener : OnItemClickListener){
        this.onClickListener = clickListener
    }

}

위에 data binding을 보시면 제가 선언 했던 변수들이 보이지요?
저기에 데이터를 넣으면 이제

        <TextView
            android:id="@+id/txt_title"
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:text="@{argTitle}" // 변수 적용 
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintStart_toEndOf="@id/img_book"
            app:layout_constraintBottom_toTopOf="@id/txt_link"
            app:layout_constraintEnd_toEndOf="parent"

            android:gravity="center"
            tools:text="제목 : 안드로이드 어플 백과 (안드로이드 유저가 반드시 챙겨야 할 머스트해브 어플 해부)"/>

        <TextView
            android:id="@+id/txt_link"
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:text="@{argLink}"// 변수 적용 
            android:gravity="center"
            app:layout_constraintTop_toBottomOf="@id/txt_title"

            app:layout_constraintStart_toEndOf="@id/img_book"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintBottom_toBottomOf="parent"
            tools:text="www.naver.com"/>

여기 xml 에 자동으로 적용됩니다.

별거 없지요? 아주 쉬위요

막상 data binding 만 하기는 쫌 그러니
recyclerview adapter 에서 원하는 책의 링크를 터치시 인터넷 으로 넘어가는 걸 만들어보겠습니다.

해당 코드는 저의 방법이지 다른분이 더 좋은 방법을 쓸수도 있습니다.

interface OnItemClickListener {
    fun onClickListener(data: String)
}

그다음 recyclerview adapter 에

private var onClickListener : OnItemClickListener ?= null

변수를 선언해주시고요

    //interface 정의
    fun setOnClickListener(clickListener : OnItemClickListener){
        this.onClickListener = clickListener
    }

이런식으로 외부에서도 접근 가능한 함수를만들어 줍니다.

그리고 원하시는 view가 클릭되는걸 만듭니다.

//recyclerview Click Listener
holder.binding.txtLink.setOnClickListener {
 onClickListener!!.onClickListener(data[position].link)
}

전 txtLink 을 터치시 클릭 이벤트를 구현했습니다

자 그럼 recyclerview 가 선언되있는 view로 넘어가지고요

    private lateinit var adapter : BookAdapter
    
        private fun init(){
        val layoutManger : RecyclerView.LayoutManager = LinearLayoutManager(requireContext())
        binding.recyclerviewBook.layoutManager = layoutManger
        adapter = BookAdapter(requireContext())
    }
    
    fun addListener(){
            adapter.setOnClickListener(object: OnItemClickListener{
            override fun onClickListener(data: String) {
                if(data == ""){
                    Log.e(TAG , "ERROR the Link is Null")
                    return
                }
                Log.d(TAG,  "The user Select book link")
                goToBookPage(data)
            }
        })
   }
}

 private fun goToBookPage(url : String){
        val intent = Intent(Intent.ACTION_VIEW, Uri.parse(url))
        startActivity(intent)
    }

data binding 된 link(string)값을
interface을 통해 함수를 만들어서 밖으로 가져왔습니다!!!

그리고 goToBookPage 이라는 함수를 통해 웹브라우져로 넘겨줬습니다!!

그럼 결과는?

성공 ~>~ 이정도는 너무 쉽제~

그럼 읽어주셔서 감사합니다

-피드백 및 오류 지적은 언제나 감사합니다-
좋은 석가탄신일 보내시길 바라겠습니다

profile
안드로이드만 좋아하는 특이한 개발자

0개의 댓글