Building an Android Search Controller

In this tutorial, Thorben illustrates how you can use the RealmSearchView library to create a filterable as-you-type search interface in less than 50 lines of code. The RealmSearchView library is implemented by extending the EditText and RecyclerView UI components and is built upon the RealmRecyclerView and RealmBasedRecyclerViewAdapter.

Estimated Time to complete: 20 minutes


The RealmSearchView is a library that renders a search bar and result list. Paired with the RealmSearchAdapter, it runs a text search against a Realm object class and displays the results. This allows for the creation of a super fast as-you-type search interface in as little as 50 lines of code!

This tutorial uses RealmSearchView v0.9.1.

After completing this tutorial you’ll be able to build a search interface like this:

search.xml

Overview

Users want to find their information as quickly as possible, especially on mobile. In many cases, search is left out by developers due to how long it can take to implement. This add-on makes it easy to add search to any of your Realm objects based on specific properties.

It’s very fast and non-blocking, revealing results as you type.

Let’s get started and create an app that uses this functionality! The application you will be building stores blog data via a Blog RealmObject as shown below:

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

}

You will implement a search feature that allows you to filter the data based upon the title of the Blog object.

You can view the full working example code on GitHub.

Getting started

Create a new Android Studio project with an Empty Activity.

RealmSearchView is available as a gradle dependency via jitpack.io. To add it you will want to add the following line to your project’s build.gradle file.

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

The result may look like this:

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

Now in your app module’s build.gradle file, add the following line

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

That’s it, re-sync the dependencies and you are ready to go.

Integration

Next, open the MainActivity’s layout file and replace the contents with the following:

<?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>

The app:rsvHint is the search text hint you can set.

Next, you’ll need to create a BlogSearchAdapter by extending the RealmSearchAdapter as shown below.

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);
        }
    }

The RealmSearchAdapter is the base adapter that facilitates the ability to perform searching and filtering on a Realm for use in a search view. The RealmSearchAdapter accepts the context, the realm, and the filterColumn name that you will be filtering upon.

The other methods of interest are:

  • onCreateRealmViewHolder: This creates the viewHolder with the view. The BlogItemView source is below.
  • onBindRealmViewHolder: This binds the blog to the view.
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());
    }
}

The BlogItemView uses the Bind annotation provided by ButterKnife in order to assist with view initialization.

Connecting The Pieces

The only thing left is to connect the RealmSearchView and the BlogSearchAdapter.

The onCreate and onDestroy methods are implemented as shown below -

@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;
    }
}

The Realm instance is provided from the Activity to the adapter via a field variable. Using a field variable ensures that the Realm can be closed when the activity is finished via the onDestroy() method in the Activity.

The above code instructs the adapter to filter the Blog objects in the Realm with the filterKey, ‘title’. Remember, the Blog type was defined in the BlogRecyclerViewAdapter class.

Lastly, the adapter is provided to the RealmSearchView via the setAdapter() method of the RealmSearchView.

Run It

That’s it! Fire up the app and you’re done! This is what you should see below if you have data in your Realm.

search.xml

You can find a full working example, with example data, and more on GitHub - https://github.com/thorbenprimke/realm-searchview


Thorben Primke

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.