Android 실시간 검색 컨트롤러 만들기

이 튜토리얼을 통해 RealmSearchView 라이브러리를 사용해서 입력하는 대로 필터 적용이 가능한 검색 인터페이스를 단 50줄 이내의 코드로 작성하는 법을 배울 수 있습니다. RealmSearchViewEditTextRecyclerView UI 컴퍼넌트를 확장했으며, RealmRecyclerViewRealmBasedRecyclerViewAdapter를 기반으로 구현된 라이브러리입니다.

예상 시간: 20분


RealmSearchView는 검색 바와 결과 목록을 렌더링하는 라이브러리입니다. RealmSearchAdapter와 함께 사용하면 Realm 객체 클래스에 대한 텍스트 검색을 실행해서 결과를 보여줄 수도 있습니다. 따라서 입력과 동시에 검색하는 인터페이스를 단 50줄도 안 되는 코드로 구현할 수 있습니다.

이 튜토리얼에서는 RealmSearchView v0.9.1을 사용합니다.

이 튜토리얼로 만들 수 있는 검색 인터페이스는 다음과 같은 모습입니다.

search.xml

개요

사용자는 가능한 한 빠르게 정보를 검색하길 원합니다. 모바일 환경이라면 더욱 그렇죠. 대부분 검색 기능의 구현 시간은 개발자에게 달려 있습니다. 이 애드온을 사용하면 특정 프로퍼티를 바탕으로 Realm 객체를 쉽게 검색할 수 있습니다.

검색의 결과는 non-blocking 방식으로 매우 빠르게 입력하는 동시에 보입니다. 이제 검색 기능이 동작하는 앱을 만들어볼까요? 이 애플리케이션은 아래처럼 Blog RealmObject에 Blog 데이터를 저장합니다.

public class Blog extends RealmObject {

   private String title;
   private String url;
   private String content;
   private String date;
   private String image;
   private String emoji;

   public Blog() {
   }

   // getters/setters/etc

}       

이런 개발 뉴스를 더 만나보세요

이제 Blog 객체의 제목으로 필터링하는 검색 기능을 구현할 차례입니다.

결과 예제 코드는 GitHub를 참고하세요.

프로젝트 준비

Empty Activity로 새 안드로이드 스튜디오 프로젝트를 만드세요.

gradle에 jitpack.io를 추가해서 RealmSearchView를 적용합니다. 프로젝트의 build.gradle 파일에 아래 코드를 넣으면 됩니다.

maven { url "https://jitpack.io" }

적용 결과는 다음과 같습니다.

allprojects {
    repositories {
        jcenter()
        maven { url "https://jitpack.io" }
    }
}

다음으로 앱의 build.gradle 파일에 다음 코드를 넣습니다.

compile 'com.github.thorbenprimke:realm-searchview:0.9.1'

적용이 끝났습니다. dependency를 다시 동기화 해주세요.

Integration

다음으로 MainActivity의 레이아웃 파일을 열어서 아래 코드로 교체합니다.

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

    <co.moonmonkeylabs.realmsearchview.RealmSearchView
        android:id="@+id/search_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:rsvHint="@string/search_hint"
        />

</FrameLayout>

app:rsvHint에서 검색을 위한 텍스트 힌트를 적용할 수 있습니다.

다음으로 아래 코드처럼 RealmSearchAdapter를 확장해서 BlogSearchAdapter를 만들어 주세요.

public class BlogRecyclerViewAdapter
            extends RealmSearchAdapter<Blog, BlogRecyclerViewAdapter.ViewHolder> {

        public BlogRecyclerViewAdapter(
                Context context,
                Realm realm,
                String filterColumnName) {
            super(context, realm, filterColumnName);
        }

        public class ViewHolder extends RealmViewHolder {

            private final BlogItemView blogItemView;

            public ViewHolder(BlogItemView blogItemView) {
                super(blogItemView);
                this.blogItemView = blogItemView;
            }
        }

        @Override
        public ViewHolder onCreateRealmViewHolder(ViewGroup viewGroup, int viewType) {
            ViewHolder vh = new ViewHolder(new BlogItemView(viewGroup.getContext()));
            return vh;
        }

        @Override
        public void onBindRealmViewHolder(ViewHolder viewHolder, int position) {
            final Blog blog = realmResults.get(position);
            viewHolder.blogItemView.bind(blog);
        }

        @Override
        public ViewHolder convertViewHolder(RealmViewHolder viewHolder) {
            return ViewHolder.class.cast(viewHolder);
        }
    }

RealmSearchAdapter는 검색 뷰에서 Realm 데이터를 찾거나 필터링할 수 있는 베이스 어댑터입니다. RealmSearchAdapter는 컨텍스트와 Realm, filterColumn 이름 등 필터링할 객체들을 받습니다.

관련 메서드는 아래와 같습니다.

  • onCreateRealmViewHolder: 뷰를 포함한 뷰홀더를 만듭니다. BlogItemView 소스 코드는 아래에 있습니다.
  • onBindRealmViewHolder: 블로그를 뷰에 바인드합니다.
public class BlogItemView extends RelativeLayout {

    @Bind(R.id.emoji)
    TextView emoji;

    @Bind(R.id.title)
    TextView title;

    @Bind(R.id.date)
    TextView date;

    @Bind(R.id.description)
    TextView description;

    public BlogItemView(Context context) {
        super(context);
        init(context);
    }

    private void init(Context context) {
        inflate(context, R.layout.blog_item_view, this);
        ButterKnife.bind(this);
    }

    public void bind(Blog blog) {
        emoji.setText(blog.getEmoji());
        title.setText(blog.getTitle());
        date.setText(blog.getDate());
        description.setText(blog.getContent());
    }
}

BlogItemViewButterKnife에서 제공하는 Bind 어노테이션을 사용해서 뷰의 초기화를 돕습니다.

구성 요소 연결

RealmSearchViewBlogSearchAdapter를 연결하는 작업만 남았습니다. onCreateonDestroy 메서드를 아래와 같이 구현해주세요.

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.search);

    RealmSearchView realmSearchView = (RealmSearchView) findViewById(R.id.search_view);

    realm = Realm.getInstance(this);
    BlogRecyclerViewAdapter adapter = new BlogRecyclerViewAdapter(this, realm, "title");
    realmSearchView.setAdapter(adapter);
}

@Override
protected void onDestroy() {
    super.onDestroy();
    if (realm != null) {
        realm.close();
        realm = null;
    }
}

액티비티는 멤버 변수를 통해 Realm 인스턴스를 어댑터에 제공합니다. 멤버 변수를 사용하면 액티비티의 onDestroy() 메서드에서 Realm을 확실히 닫을 수 있습니다.

위 코드에서는 RealmBlog 객체를 ‘title’ filterKey를 사용해서 필터링하도록 어댑터에 지시합니다. Blog 타입은 BlogRecyclerViewAdapter 클래스에서 정의했음을 기억해 주세요.

마지막으로 RealmSearchViewsetAdapter() 메서드를 통해 adapterRealmSearchView에 제공됩니다.

실행

모든 튜토리얼이 끝났습니다. 앱을 실행해 보세요. Realm에 데이터가 있다면 아래와 같은 결과가 보일 겁니다.

search.xml

실행 가능한 전체 코드와 예제 데이터, 그 밖의 정보는 GitHub - https://github.com/thorbenprimke/realm-searchview에서 볼 수 있습니다.

다음: 안드로이드를 위한 Realm #3: 동기 Realm 마이그레이션 가이드

General link arrow white

컨텐츠에 대하여

이 컨텐츠는 저자의 허가 하에 이곳에서 공유합니다.


Thorben Primke

Thorben is a Software Engineer at Pinterest working towards making all product pins buyable. Prior to Pinterest he worked on Android at Jelly, Facebook, and Gowalla.

4 design patterns for a RESTless mobile integration »

close