안드로이드 DataBinding : RecyclerView

elice dev
8 min readDec 3, 2017

데이터바인딩은 애플리케이션 로직과 레이아웃을 바인딩하는 데 필요한 글루 코드를 최소화합니다. 글루코드는 아래 설명으로 대신합니다.

In computer programming, glue code is source code that serves solely to “adapt” different parts of code that would otherwise be incompatible.

그럼 데이터 바인딩을 시작해보겠습니다. 먼저, app모듈의 build.gradle에 아래 코드만 추가하면 데이터바인딩 빌드환경이 준비된것입니다. 간단하죠?

android {
....
dataBinding {
enabled = true
}
}

https://www.androidhive.info/2016/01/android-working-with-recycler-view/ 해당 사이트의 recylcerView 예제를 데이터바인딩으로 바꿔보겠습니다. 가장 먼저, 레이아웃을 바꿀게요.

<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:bind="http://schemas.android.com/tools">

<data>

<import type="android.databinding.ObservableArrayList" />
<import type="data.app.databindingtest.Movie" />

<variable
name="movieList"
type="ObservableArrayList&lt;Movie&gt;" />
</data>

<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent">

<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layoutManager="LinearLayoutManager"
bind:item="@{movieList}" />

</LinearLayout>

</layout>

기존의 레이아웃과 다르게 <layout>태그로 감싸고 있어야 뷰에서 바인딩클래스가 생성됩니다. 저는 데이터가 계속 변경될때마다 UI도 자동으로 업데이트 되기 위해서 ObservableArrayList로 선언했습니다. UI에 바인딩되어 있고ObservableArrayList를 통해서 데이터 객체의 속성이 변경되면 UI가 자동으로 업데이트되기 때문입니다. 즉, 데이터가 변경될때마다 데이터를 set할 필요가 없습니다.

그리고 xml이기 때문에 ObservableArrayList<Movie>에서의 generic형태의 <> 괄호가 &lt;Movie&gt; 로 나타내야 합니다.

위처럼 레이아웃 수정 후, 빌드하게 되면 아래와 같이 ActivityMainBinding클래스가 생성됩니다. 바인딩은 View 계층 구조에서 한 번 전달하여 ID가 있는 View를 추출하므로 recyclerView = findViewById(R.id.recyclerView); 라고 할필요 없이layout에서 ID 값을 지정한대로 binding.recyclerView로 사용할 수 있습니다.

private ObservableArrayList<Movie> movieList;
private MoviesAdapter mAdapter;

@Override
protected void onCreate
(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ActivityMainBinding binding = DataBindingUtil.setContentView(this, R.layout.activity_main);

mAdapter = new MoviesAdapter();
movieList = new ObservableArrayList<>();
binding.recyclerView.setAdapter(mAdapter);
binding.setMovieList(movieList);

prepareMovieData();
}

레이아웃에서 bind:item=”@{movieList}” 로 선언한 것에서 알 수 있듯이 어딘가에서 item을 넘겨준다는것을 추측할 수 있습니다. 맞습니다. 이럴때, @BindingAdapter를 사용합니다. 기존에 binding.setMovieList(movieList);를 했기 때문에, movieList 를 참조하고 있고, 리스트에 데이터가 더해지면 @BindingAdapter를 통해 어댑터로 데이터를 set해주는 역할을 합니다.

@BindingAdapter("bind:item")
public static void bindItem
(RecyclerView recyclerView, ObservableArrayList<Movie> movie) {
MoviesAdapter adapter =(MoviesAdapter)recyclerView.getAdapter();
if (adapter != null) {
adapter.setItem(movie);
}
}

위처럼 adapter로 넘겨진 데이터는 onCreateViewHolderonBindViewHolder 를 통해 바인딩 됩니다. item_movie_list.xml을 네이밍으로 하였기 때문에 ItemMovieListBinding바인딩 객체가 생성되었습니다.

@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
ItemMovieListBinding binding = ItemMovieListBinding.
inflate(LayoutInflater.from(parent.getContext()), parent, false);
return new MyViewHolder(binding);
}
@Override
public void onBindViewHolder
(MyViewHolder holder, int position) {
Movie movie = moviesList.get(position);
holder.bind(movie);
}
void setItem(List<Movie> movie) {
if (movie == null) {return;}
this.moviesList = movie;
notifyDataSetChanged();
}

기존에 onBindViewHolder 메서드에서 holder.title.setText(“movie”);와 같은 형태였다면, 데이터바인딩에서는 아래와 같이 binding.setVariable(BR.movie, movie); 또는 binding.setMovie(movie); 으로 완성이 됩니다. 이유는 layout에서 android:text=@{movie.title}처럼 바인딩하고 있기 때문입니다. (레이아웃은 깃헙소스에 자세히 설명되어있습니다)

class MyViewHolder extends RecyclerView.ViewHolder {
ItemMovieListBinding binding;

MyViewHolder(ItemMovieListBinding binding) {
super(binding.getRoot());
this.binding = binding;
}

void bind(Movie movie) {
binding.setVariable(BR.movie, movie);
}
}

DataBinding을 사용해보니, 이점으로는findViewById(R.id.recyclerView); 코드가 필요 없어지는 점과 xml에서 바인딩하기 때문에 RecyclerView Adapter에서 각 데이터를 일일이 set해주지 않아도 되서 java코드가 줄어든다는 점이 가장 컸습니다. 그리고 무엇보다 직접 코딩하면서 몸소 느꼈습니다.

하지만 단점을 굳이 꼽자면, 그에 비해 레이아웃의 코드가 많아진다는점, 바인딩에러나서 수정해도 클린하고 다시 빌드해야 해결될때가 있다는 점 등이 있었습니다.

지금까지 설명드렸던 예제들과 위의 응용 동작은 Github에서 샘플 프로젝트로 확인 해보실 수 있습니다.

https://github.com/Elice-kim/EliceDataBinding

[도움이 되셨다면 깃헙 오른쪽 위의 star버튼을 눌러주세요!]

--

--