SearchView en bases de datos es una funcionalidad bastante básica que puedes ver en la mayoría de las aplicaciones en tu día a día, entonces por qué no, debes aprenderla e implementarla. no es demasiado complicado de implementar en su aplicación. Hay muchas maneras más fáciles de implementarlo. Las tareas que debe usar para implementar searchView en la aplicación son: –
- Debe crear un elemento de menú que configure actionViewClass en SearchView y establecer otros atributos de vista de acción
- Luego infle el menú en el método onCreateOptionsMenu() de la acción donde desea la función de búsqueda.
- Luego obtenga el objeto SearchView del menú y agréguele SearchView.OnQueryTextListener llamando al método setOnQueryTextListener.
- SearchView.OnQueryTextListener tiene dos métodos de devolución de llamada onQueryTextSubmit y onQueryTextChange
- Se llama al método onQueryTextSubmit cuando el usuario envía una búsqueda presionando el botón Intro o haciendo clic en el botón Enviar en el widget de búsqueda.
En este método, la búsqueda en la base de datos se puede realizar usando el texto ingresado en el widget de vista de búsqueda. Puede habilitar el botón de búsqueda en el widget de vista de búsqueda llamando al método setSubmitButtonEnabled y pasando el valor booleano de verdadero. es una idea básica de cómo funciona. Pero vamos a discutir la forma más eficiente de buscar datos de la base de datos de la sala, para eso, debe conocer algunos conceptos como:
requisitos previos:
- Cómo mostrar datos en recyclerView usando room DB (qué es el adaptador)
- ¿Qué es la base de datos ROOM (biblioteca) ?
- Familiarizado con la arquitectura Model-View-ViewModel (MVVM)
- La más importante es la inyección de dependencia (empuñadura de daga)
Aparte de eso, no vamos a crear una aplicación desde cero, estamos proporcionando el código fuente para cosas iniciales como
- Actualización de datos en RecyclerView por base de datos
- Usando la inyección de dependencia
- y también creó algunas clases adicionales
Le estamos dando una descripción general rápida del proyecto, luego lo entenderá muy fácilmente. Descarga el proyecto haciendo Click Aquí .
Implementación paso a paso
Paso 1: descargue el proyecto de GitHub y agréguelo a su estudio de Android
Esperamos que todos sepan cómo importar proyectos existentes al estudio de Android si no lo hacen, luego vayan a archivo> abrir> seleccione el proyecto descargado> luego espere … para finalizar la construcción del proyecto
Paso 2: compilar archivos Gradle
Vaya a la aplicación > Gradle Scripts > archivo build.Gradle y agregue las siguientes dependencias en la sección de dependencias.
- Hemos agregado algunas dependencias y complementos.
- y habilitar el enlace de vista
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" }
Paso 3: Creación de entidad/tabla
Vaya a aplicación > principal > searchViewInRoom > datos > person.kt. Así es como podemos crear una entidad/tabla en la base de datos SQLite usando la sala
Kotlin
package com.example.searchViewInRoom.data import androidx.room.Entity import androidx.room.PrimaryKey // it's our data class that we have // annotate @Entity to create it as table @Entity(tableName = "person_table") data class Person( // table is basically // having 3 fields as follow.... var firstName: String, var lastName: String, var age: Int ){ @PrimaryKey(autoGenerate = true) // we make id as primary // key and it will autogenerate var id: Int = 0 }
Paso 4: Crear una base de datos
Vaya a aplicación > principal > searchViewInRoom>data > personDatabase.kt. Así es como puedes crear una base de datos. Por favor, lea los comentarios para una mejor comprensión.
Kotlin
package com.example.searchViewInRoom.data import androidx.room.Database import androidx.room.RoomDatabase // it's our database and here we // specify entities, our version and exportSchema @Database( entities = [Person::class], version = 1, exportSchema = false ) // in our database we have just extended RoomDatabase class abstract class PersonDatabase: RoomDatabase() { // as you can see it is our abstract fun and // it represent our Data Access Object (dao) abstract fun personDao(): PersonDao }
Paso 5: clase de módulo de base de datos
Vaya a aplicación > principal > searchViewInRoom > di > DatabaseModule.kt. Aquí usamos la inyección de dependencia
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 // this is a very important step actually // here we used dependency injection library dagger hilt // it actually provide our database object and dao @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() }
Paso 6: Clase Dao (objeto de acceso a datos)
Vaya a la aplicación> principal> 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 // here we have our Dao having three // different queries as follows..... @Dao interface PersonDao { // it's basically for reading our database @Query("SELECT * FROM person_table ORDER BY id ASC") fun readData(): Flow<List<Person>> // it's for inserting person object to our database @Insert(onConflict = OnConflictStrategy.REPLACE) suspend fun insertData(person: Person) // it's very important one for this article because //it's a query for searching our database /* so here we have written basic sql query for searching our database basically will search from our person table or entity where our first name and last name contains some characters from our searchquery */ @Query("SELECT * FROM person_table WHERE firstName LIKE :searchQuery OR lastName LIKE :searchQuery") // and then search query will be passed through // the perimeter of this function // and then function will return the flow of list of person fun searchDatabase(searchQuery: String): Flow<List<Person>> }
Paso 7: crear una clase de repositorio
Vaya a la aplicación> principal> searchViewInRoom> datos> Repository.kt
Kotlin
package com.example.searchViewInRoom.data import kotlinx.coroutines.flow.Flow import javax.inject.Inject // it's repository /* here we have basically injected our person Dao for our dao interface and having three function as well........ */ 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) } }
Paso 8: Modelo de vista principal
Vaya a aplicación > principal > buscarViewInRoom>viewmodel > MainViewModel.kt. Vamos a utilizar este módulo para recibir y observar datos de la base de datos.
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 // here we have our viewModel // and we are going to use it for receiving // and observing data from our database 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() } }
Todas estas clases mencionadas anteriormente ya están en el proyecto que ha descargado, y es una descripción general rápida. Ahora pasemos a la parte XML del proyecto dado…
archivo actividad_principal.xml
Ahora tenemos que navegar a aplicación > res > actividad_principal.xml y comprender el siguiente código.
XML
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <!--recycler view for displaying all data --> <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> <!--fab for adding dummy data --> <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>
archivo row_layout.xml
Es una vista de elementos, que tenemos que agregar en RecyclerView
XML
<?xml version="1.0" encoding="utf-8"?> <androidx.cardview.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" 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>
eso es todo para todo el proyecto que te he dado. Después de eso, tu aplicación debería verse así …
Pero si se muestra la lista dada, muy bien, de lo contrario, no se preocupe, lo administraremos. ahora comencemos la parte real del artículo (implementación de SearchView). S olo hay tres pasos para implementar su función de búsqueda, que son los siguientes…
- agregar icono de búsqueda en cualquier lugar de la pantalla
- anular el método onCreateOptionsMenu()
- luego implemente onQueryTextListner en nuestra actividad principal
eso es todo. así que hagámoslos.
Paso 1: agregue el ícono de búsqueda en cualquier lugar de la pantalla
Lo estamos agregando en la esquina superior derecha de la aplicación. Para eso, debe crear un elemento de menú, mediante administrador de recursos> menú> agregar archivo de recursos de menú
XML
<?xml version="1.0" encoding="utf-8"?> <menu xmlns:tools="http://schemas.android.com/tools" xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto"> <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>
Paso 2: invalidar el método onCreateOptionsMenu()
Vaya a MainActivity.kt. Ya tiene algo de código, pero lea los comentarios, lo mencioné allí y también puede entenderlo fácilmente.
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(){ // as you can see this is my main activity and // here we have created view binding for binding our views private lateinit var binding: ActivityMainBinding // here we have initialized our mainViewModel private val mainViewModel: MainViewModel by viewModels() // and recycler view adapter private val myAdapter: MyAdapter by lazy { MyAdapter() } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) binding = ActivityMainBinding.inflate(layoutInflater) setContentView(binding.root) // here we are using linear layout manager for our recyclerView binding.recyclerView.layoutManager = LinearLayoutManager(this) // here we are setting my recyclerView // to custom adapter that we have already made binding.recyclerView.adapter = myAdapter // here we are observing data by mainViewModel // using readData variable mainViewModel.readData.observe(this, { // using custom recyclerView adapter we have // set the data to our recycler view myAdapter.setData(it) }) } }
Después de comprender el código anterior, simplemente obtenga la anulación onCreateOptionsMenu()
- para obtener solo presione ctrl + o y busque esta función, luego presione enter
- tenemos que anular esta función para que podamos agregar nuestro menú aquí como se muestra a continuación.
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 // here you get error but don't worry searchView?.setOnQueryTextListener(this) return true }
Después del paso 2, su actividad principal se verá así…
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 { // as you can see this is my main activity and // here we have created view binding for binding our views private lateinit var binding: ActivityMainBinding // here we have initialized our mainViewModel private val mainViewModel: MainViewModel by viewModels() // and recycler view adapter private val myAdapter: MyAdapter by lazy { MyAdapter() } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) binding = ActivityMainBinding.inflate(layoutInflater) setContentView(binding.root) // here we are using linear layout manager for our recyclerView binding.recyclerView.layoutManager = LinearLayoutManager(this) // here we are setting my recyclerView to // custom adapter that i have already made binding.recyclerView.adapter = myAdapter // here we are observing data by mainViewModel // using readData variable mainViewModel.readData.observe(this, { // using custom recyclerView adapter // we have set the data to our recycler view 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 }
Paso 3: implementar onQueryTextListner en MainActivity.kt
Para implementar su setOnQueryTextListener en la actividad principal para pasar ‘esto’ como perímetro
- para la implementación, simplemente vaya arriba y agregue, SearchView.OnQueryTextListener después de la clase MainActivity: AppCompatActivity() como…. clase MainActivity: AppCompatActivity(), SearchView.OnQueryTextListener
- después de que se muestre otro error, simplemente mueva el cursor sobre el error y presione alt+Enter
- entonces tendrá dos funciones llamadas onQueryTextChange() , onQueryTextChange()
- entonces simplemente implemente estas dos funciones como
Kotlin
override fun onQueryTextSubmit(query: String?): Boolean { // it will triggered when // we submit the written test return true } // this function will triggered when we // write even a single char in search view override fun onQueryTextChange(query: String?): Boolean { if(query != null){ searchDatabase(query) } return true } // We have just created this function for searching our database private fun searchDatabase(query: String) { // %" "% because our custom sql query will require that val searchQuery = "%$query%" mainViewModel.searchDatabase(searchQuery).observe(this, { list -> list.let { myAdapter.setData(it) } })
¡sí! Hemos implementado con éxito una función de búsqueda. Puede descargar el código fuente final haciendo clic aquí .
Ahora ejecute su aplicación y vea. ¿Su aplicación muestra datos ficticios en la vista del reciclador? si es así, entonces lo ha hecho ahora puede buscar algo y le mostrará los resultados,
Pero si no, agregue algunos datos ficticios siguiendo algunos pasos como…
- cree una función como «fun additem()» dentro de su clase MainActivity.kt
- luego inserte datos usando mainViewModel.insertData(Person(“string : name”, “string: lastname”, int :age)) como se muestra a continuación en el código
- ahora simplemente llame a la función additem() cuando se haga clic en el botón de acción flotante o como quiera.
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)) }
- si desea insertar datos usando el botón de acción flotante
- luego simplemente agregue esta línea a su código de botón de acción flotante
android:onClick=”elemento adicional”
Eso es todo, sus datos también se mostrarán en su aplicación y ahora también puede verificar la búsqueda ……. finalmente, la aplicación está funcionando como
Producción:
Publicación traducida automáticamente
Artículo escrito por eralokyadav2019 y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA