SearchView in databases is a pretty basic functionality that you can see in most of the applications in your day-to-day life, then why not, you should learn and implement it. it is not too much complicated to implement in your application. There are a lot of easier ways that are how you can implement it. The tasks that you should use to implement for implementing searchView in-app are:-
- You need to create a menu item setting actionViewClass to SearchView and set other action view attributes
- Then inflate the menu in the onCreateOptionsMenu() method of the action where you want the search feature.
- Then get the SearchView object from the menu and add SearchView.OnQueryTextListener to it by calling setOnQueryTextListener method.
- SearchView.OnQueryTextListener has two callback methods onQueryTextSubmit and onQueryTextChange
- Method onQueryTextSubmit gets called when the user submits a search by hitting enter button or clicking submit button on the search widget.
In this method, database search can be performed using the text entered into the search view widget. You can enable the search button in the search view widget by calling the setSubmitButtonEnabled method and passing the boolean value of true. it’s a basic idea that how it works. But we are going to discuss the most efficient way for searching data from the room database, for that, you should know about some concepts like:
Prerequisites:
We are not going to create an app from scratch apart from that, we are providing the source code for initial things like
- Updating data in RecyclerView by database
- Using dependency injection
- and created some extra classes as well
We are giving you a quick overview of the project, then you will understand it very easily. Download the project by Click Here.
Step by Step Implementation
Step 1: Download the project from GitHub and Add it to your android studio
We hope you all know that how to import existing projects to the android studio if don’t then go to file > open > select downloaded project > then wait… for finish project build
Step 2: build.Gradle files
Navigate to the app > Gradle Scripts > build.Gradle file and add the below dependencies in the dependencies section.
- We have added some dependencies and plugins
- and enable view binding
plugins {
id 'com.android.application'
id 'kotlin-android'
id 'kotlin-kapt' // dagger hilt plugin
id 'dagger.hilt.android.plugin'
}
android {
compileSdkVersion 30
buildToolsVersion "30.0.2"
defaultConfig {
applicationId "com.example.searchViewInRoom"
minSdkVersion 21
targetSdkVersion 30
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
// here we have enabled viewBinding
buildFeatures {
viewBinding true
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
}
}
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation 'androidx.core:core-ktx:1.3.2'
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'com.google.android.material:material:1.2.1'
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
testImplementation 'junit:junit:4.13.1'
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
// Navigation Component
implementation 'androidx.navigation:navigation-fragment-ktx:2.3.2'
// Room components
implementation "androidx.room:room-runtime:2.2.6"
kapt "androidx.room:room-compiler:2.2.6"
implementation "androidx.room:room-ktx:2.2.6"
androidTestImplementation "androidx.room:room-testing:2.2.6"
// Dagger - Hilt
implementation "com.google.dagger:hilt-android:2.28.3-alpha"
kapt "com.google.dagger:hilt-android-compiler:2.28.3-alpha"
implementation "androidx.hilt:hilt-lifecycle-viewmodel:1.0.0-alpha02"
kapt "androidx.hilt:hilt-compiler:1.0.0-alpha02"
// Lifecycle
implementation "androidx.lifecycle:lifecycle-extensions:2.2.0"
implementation "androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0"
implementation "androidx.lifecycle:lifecycle-livedata-ktx:2.2.0"
}
Step 3: Creating Entity/Table
Go to app > main > searchViewInRoom > data > person.kt. This is how we can create an entity/table in SQLite database using room
Kotlin
package com.example.searchViewInRoom.data
import androidx.room.Entity
import androidx.room.PrimaryKey
@Entity (tableName = "person_table" )
data class Person(
var firstName: String,
var lastName: String,
var age: Int
){
@PrimaryKey (autoGenerate = true )
var id: Int = 0
}
|
Step 4: Create a database
Go to app > main > searchViewInRoom>data > personDatabase.kt. This is how you can create a database. Please read the comments for a better understanding.
Kotlin
package com.example.searchViewInRoom.data
import androidx.room.Database
import androidx.room.RoomDatabase
@Database (
entities = [Person:: class ],
version = 1 ,
exportSchema = false
)
abstract class PersonDatabase: RoomDatabase() {
abstract fun personDao(): PersonDao
}
|
Step 5: Database module class
Go to app > main > searchViewInRoom > di > DatabaseModule.kt. Here we use dependency injection
Kotlin
package com.example.searchViewInRoom.di
import android.content.Context
import androidx.room.Room
import com.example.searchViewInRoom.data.PersonDatabase
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.components.ApplicationComponent
import dagger.hilt.android.qualifiers.ApplicationContext
import javax.inject.Singleton
@Module
@InstallIn (ApplicationComponent:: class )
object DatabaseModule {
@Singleton
@Provides
fun provideDatabase(
@ApplicationContext context: Context
) = Room.databaseBuilder(
context,
PersonDatabase:: class .java,
"person_database"
).build()
@Singleton
@Provides
fun provideDao(database: PersonDatabase) = database.personDao()
}
|
Step 6: Dao (Data Access Object) Class
Go to app > main > searchViewInRoom>data > personDao.kt
Kotlin
package com.example.searchViewInRoom.data
import androidx.room.Dao
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import kotlinx.coroutines.flow.Flow
@Dao
interface PersonDao {
@Query ( "SELECT * FROM person_table ORDER BY id ASC" )
fun readData(): Flow<List<Person>>
@Insert (onConflict = OnConflictStrategy.REPLACE)
suspend fun insertData(person: Person)
@Query ( "SELECT * FROM person_table WHERE firstName LIKE :searchQuery OR lastName LIKE :searchQuery" )
fun searchDatabase(searchQuery: String): Flow<List<Person>>
}
|
Step 7: Creating a Repository Class
Go to app > main > searchViewInRoom > data > Repository.kt
Kotlin
package com.example.searchViewInRoom.data
import kotlinx.coroutines.flow.Flow
import javax.inject.Inject
class Repository @Inject constructor(
private val personDao: PersonDao
) {
fun readData(): Flow<List<Person>> {
return personDao.readData()
}
suspend fun insertData(person: Person) {
personDao.insertData(person)
}
fun searchDatabase(searchQuery: String): Flow<List<Person>> {
return personDao.searchDatabase(searchQuery)
}
}
|
Step 8: MainViewModel
Go to app > main > searchViewInRoom>viewmodel > MainViewModel.kt. We are going to use this module to receive and observe data from the database.
Kotlin
package com.example.searchViewInRoom.viewmodel
import androidx.hilt.lifecycle.ViewModelInject
import androidx.lifecycle.LiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.asLiveData
import androidx.lifecycle.viewModelScope
import com.example.searchViewInRoom.data.Person
import com.example.searchViewInRoom.data.Repository
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
class MainViewModel @ViewModelInject constructor(
private val repository: Repository
) : ViewModel() {
val readData = repository.readData().asLiveData()
fun insertData(person: Person){
viewModelScope.launch(Dispatchers.IO) {
repository.insertData(person)
}
}
fun searchDatabase(searchQuery: String): LiveData<List<Person>> {
return repository.searchDatabase(searchQuery).asLiveData()
}
}
|
These all the classes mentioned above are already in the project that you have downloaded, and it’s a quick overview. Now let’s move to the XML part of the given project …
activity_main.xml file
Now we have to navigate to app > res > activity_main.xml and Understand the below code.
XML
<? xml version = "1.0" encoding = "utf-8" ?>
< androidx.constraintlayout.widget.ConstraintLayout
android:layout_width = "match_parent"
android:layout_height = "match_parent"
tools:context = ".MainActivity" >
< androidx.recyclerview.widget.RecyclerView
android:id = "@+id/recyclerView"
android:layout_width = "match_parent"
android:layout_height = "match_parent"
app:layout_constraintBottom_toBottomOf = "parent"
app:layout_constraintEnd_toEndOf = "parent"
app:layout_constraintHorizontal_bias = "0.0"
app:layout_constraintStart_toStartOf = "parent"
app:layout_constraintTop_toTopOf = "parent"
app:layout_constraintVertical_bias = "0.0"
tools:listitem = "@layout/row_layout" >
</ androidx.recyclerview.widget.RecyclerView >
< com.google.android.material.floatingactionbutton.FloatingActionButton
android:id = "@+id/floatingActionButton"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:clickable = "true"
app:layout_constraintBottom_toBottomOf = "parent"
app:layout_constraintEnd_toEndOf = "parent"
app:layout_constraintHorizontal_bias = "0.954"
app:layout_constraintStart_toStartOf = "parent"
app:layout_constraintTop_toTopOf = "parent"
app:layout_constraintVertical_bias = "0.976"
android:backgroundTint = "#098043"
app:srcCompat = "@android:drawable/ic_input_add"
tools:ignore = "SpeakableTextPresentCheck,ImageContrastCheck"
android:focusable = "true" />
</ androidx.constraintlayout.widget.ConstraintLayout >
|
row_layout.xml file
It’s an item view, that we have to add in RecyclerView
XML
<? xml version = "1.0" encoding = "utf-8" ?>
< androidx.cardview.widget.CardView
android:layout_width = "match_parent"
android:layout_height = "wrap_content"
app:cardCornerRadius = "5dp"
android:padding = "5dp"
android:layout_margin = "5dp"
app:cardBackgroundColor = "#B9F6CA" >
< RelativeLayout
android:layout_width = "wrap_content"
android:layout_height = "wrap_content" >
< TextView
android:id = "@+id/firstName_textView"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:layout_marginStart = "10dp"
android:layout_marginTop = "10dp"
android:layout_marginEnd = "10dp"
android:layout_marginBottom = "10dp"
android:fontFamily = "@font/jockey_one"
android:text = "krish"
android:textColor = "@color/black"
android:textSize = "24sp" />
< TextView
android:id = "@+id/lastName_textView"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:layout_marginTop = "10dp"
android:fontFamily = "@font/jockey_one"
android:layout_marginBottom = "10dp"
android:layout_toEndOf = "@+id/firstName_textView"
android:text = "moris"
android:textColor = "@color/black"
android:textSize = "24sp" />
< TextView
android:id = "@+id/age_textView"
android:layout_width = "wrap_content"
android:layout_height = "wrap_content"
android:layout_alignParentEnd = "true"
android:layout_marginTop = "10dp"
android:layout_marginRight = "30dp"
android:text = "20"
android:textColor = "@color/black"
android:textSize = "24sp"
android:textStyle = "bold" />
</ RelativeLayout >
</ androidx.cardview.widget.CardView >
|
that’s it for the whole project that I have given to you, After that your app should look like this ……
But if the given list is shown then well and good otherwise don’t worry, we will manage it. now let’s start the real part of the article (implementation of SearchView). There are only three steps to implement your search functionality, which are as follows…
- add search icon anywhere on the screen
- override onCreateOptionsMenu() method
- then implement onQueryTextListner in our mainActivity
that’s it. so let’s do them.
Step 1: Add search icon anywhere on the screen
We are adding it at the top right corner of the app. For that, you have to create a menu item, by resource manager > menu > add menu resource file
XML
<? xml version = "1.0" encoding = "utf-8" ?>
< item android:id = "@+id/menu_search"
android:title = "@string/search"
android:icon = "@drawable/ic_search"
android:iconTint = "@color/white"
app:showAsAction = "ifRoom"
app:actionViewClass = "androidx.appcompat.widget.SearchView" />
</ menu >
|
Step 2: override onCreateOptionsMenu() method
Go to MainActivity.kt. It has some code already, but read the comments, I mentioned there and you can easily understand it as well.
Kotlin
package com.example.searchViewInRoom
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.Menu
import android.widget.Toast
import androidx.activity.viewModels
import androidx.appcompat.widget.SearchView
import androidx.recyclerview.widget.LinearLayoutManager
import com.example.searchViewInRoom.adapter.MyAdapter
import com.example.searchViewInRoom.data.Person
import com.example.searchViewInRoom.databinding.ActivityMainBinding
import com.example.searchViewInRoom.viewmodel.MainViewModel
import dagger.hilt.android.AndroidEntryPoint
@AndroidEntryPoint
class MainActivity : AppCompatActivity(){
private lateinit var binding: ActivityMainBinding
private val mainViewModel: MainViewModel by viewModels()
private val myAdapter: MyAdapter by lazy { MyAdapter() }
override fun onCreate(savedInstanceState: Bundle?) {
super .onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
binding.recyclerView.layoutManager = LinearLayoutManager( this )
binding.recyclerView.adapter = myAdapter
mainViewModel.readData.observe( this , {
myAdapter.setData(it)
})
}
}
|
After understanding the above code, just get the override onCreateOptionsMenu()
- for getting just press ctrl+o and search this function then press enter
- we have to override this function so that we can add our menu here as shown below.
Kotlin
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
menuInflater.inflate(R.menu.main_menu, menu)
val search = menu?.findItem(R.id.menu_search)
val searchView = search?.actionView as? SearchView
searchView?.isSubmitButtonEnabled = true
searchView?.setOnQueryTextListener( this )
return true
}
|
After step 2 your main activity will look like this…
Kotlin
package com.example.searchViewInRoom
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.view.Menu
import android.widget.Toast
import androidx.activity.viewModels
import androidx.appcompat.widget.SearchView
import androidx.recyclerview.widget.LinearLayoutManager
import com.example.searchViewInRoom.adapter.MyAdapter
import com.example.searchViewInRoom.data.Person
import com.example.searchViewInRoom.databinding.ActivityMainBinding
import com.example.searchViewInRoom.viewmodel.MainViewModel
import dagger.hilt.android.AndroidEntryPoint
@AndroidEntryPoint
class MainActivity : AppCompatActivity(), SearchView.OnQueryTextListener {
private lateinit var binding: ActivityMainBinding
private val mainViewModel: MainViewModel by viewModels()
private val myAdapter: MyAdapter by lazy { MyAdapter() }
override fun onCreate(savedInstanceState: Bundle?) {
super .onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
binding.recyclerView.layoutManager = LinearLayoutManager( this )
binding.recyclerView.adapter = myAdapter
mainViewModel.readData.observe( this , {
myAdapter.setData(it)
})
}
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
menuInflater.inflate(R.menu.main_menu, menu)
val search = menu?.findItem(R.id.menu_search)
val searchView = search?.actionView as? SearchView
searchView?.isSubmitButtonEnabled = true
searchView?.setOnQueryTextListener( this )
return true
}
|
Step 3: Implement onQueryTextListner in MainActivity.kt
To implement your setOnQueryTextListener in main activity for pass ‘this’ as perimeter
- for implementation just go above and add, SearchView.OnQueryTextListener after class MainActivity : AppCompatActivity() like…. class MainActivity : AppCompatActivity(), SearchView.OnQueryTextListener
- after another error will show, just move the cursor on error and press alt+Enter
- then you will have two functions named onQueryTextChange() , onQueryTextChange()
- then just implement these two functions as
Kotlin
override fun onQueryTextSubmit(query: String?): Boolean {
return true
}
override fun onQueryTextChange(query: String?): Boolean {
if (query != null ){
searchDatabase(query)
}
return true
}
private fun searchDatabase(query: String) {
val searchQuery = "%$query%"
mainViewModel.searchDatabase(searchQuery).observe( this , { list ->
list.let {
myAdapter.setData(it)
}
})
|
yeah! we have successfully implemented a search feature. you can download the final source code by click here.
Now run your app and see. Is your app showing dummy data in recycler view? if yes then you have done it now you can search for something and it will show you results,
But if don’t then add some dummy data using some steps as…
- create a function like “fun additem()” inside your MainActivity.kt class
- then insert data using mainViewModel.insertData(Person(“string : name”, “string: lastname”, int :age)) as shown below in code
- now just call additem() function when the floating action button is clicked or however, you want.
Kotlin
fun additem(view: android.view.View) {
mainViewModel.insertData(Person( "Krish" , "joshi" , 18 ))
mainViewModel.insertData(Person( "Sukant" , "desai" , 38 ))
mainViewModel.insertData(Person( "Anye" , "jems" , 40 ))
mainViewModel.insertData(Person( "Geek" , "geek" , 76 ))
mainViewModel.insertData(Person( "Alok" , "pro" , 45 ))
mainViewModel.insertData(Person( "Kushi" , "singh" , 34 ))
mainViewModel.insertData(Person( "Final" , "step" , 23 ))
mainViewModel.insertData(Person( "Vidyut" , "sharma" , 20 ))
mainViewModel.insertData(Person( "Ankit" , "chaudhary" , 19 ))
mainViewModel.insertData(Person( "Abhay" , "yadav" , 16 ))
}
|
- if you want to insert data using the floating action button
- then just add this line to your floating action button code
android:onClick=”additem”
That’s it your data will also be shown in your app and now you can also check for search…….finally, the app is working like
Output:
Last Updated :
18 Oct, 2021
Like Article
Save Article
Share your thoughts in the comments
Please Login to comment...