Android'de Firebase Firestore kullanarak anlık anahtar kelime araması

2 hafta önce , Okuma süresi 3 dakika.

Herhangi bir web sitesi veya web uygulaması oluşturmanın en önemli kısımlarından biri, arama işlevidir. Bu uygulamada anlık arama yapmanını mantığını uygulamalı olarak anlatacağız.
Android'de Firebase Firestore kullanarak anlık anahtar kelime araması

Arama işlevi, ürünlerle etkileşimi daha kolay ve daha hızlı hale getirmeye yardımcı olur. Her milisaniyenin önemli olduğu ve kötü bir arama deneyiminin kullanıcıların bir ürünü kullanmayı bırakmalarına neden olabileceği bir dünyada yaşıyoruz.

Anında Arama nedir?

Bu, bir kullanıcının arama sorgusunun en olası tamamlanmasını tahmin etmeye ve tahmin etmeye çalışan ve arama kutusuna girilen her tuş vuruşuyla kullanıcının girişiyle ilgili bilgileri anında görüntüleyen tahmini bir arama özelliğidir.

Ön koşullar:

Android, Firestore ve Kotlin'in temellerini bilmelisiniz.

Neyi uygulayacağız:

 Gönderi için resim

Başlangıç:

Firestore'un en önemli kısmı veritabanı yapısını tanımlamaktır. Böylece her bir anahtar kelimeyi sorgulayabilir ve onu gerçek görüntüleme sonucumuzla eşleştirebiliriz.

Gönderi için resim Firestore Veritabanı Yapısı

Hadi biraz kod yapalım:

Arama araç çubuğu düzeni için bir yerleşim dosyası search_toolbar_custom_view.xml oluşturun .

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout 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="?attr/actionBarSize">

    <ImageView
        android:id="@+id/search_icon"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_alignParentStart="true"
        android:contentDescription="@string/search_icon"
        android:paddingStart="16dp"
        android:paddingEnd="16dp"
        android:src="@drawable/ic_search"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <EditText
        android:id="@+id/search_edittext"
        android:layout_width="0dp"
        android:layout_height="match_parent"
        android:layout_alignParentEnd="true"
        android:layout_toEndOf="@id/search_icon"
        android:autofillHints="@string/search"
        android:background="@drawable/search_edittext_"
        android:hint="@string/search"
        android:inputType="text"
        android:maxLines="1"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toEndOf="@+id/search_icon"
        app:layout_constraintTop_toTopOf="parent" />
    

</RelativeLayout>

Bir Oluşturma ArrayAdapter.kt için sınıf recyclerview .

class ArrayAdapter(private var suggestions: List<String>, private val activity: Activity) :
    RecyclerView.Adapter<ArrayAdapter.ViewHolder>() {
    
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        val inflate = LayoutInflater.from(parent.context)
            .inflate(R.layout.suggestion_textview_item, parent, false)
        return ViewHolder(inflate, activity)
    }

    override fun getItemCount(): Int {
        return suggestions.size
    }

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        holder.bind(suggestions[position])
    }

    fun setList(suggestionList: List<String>) {
        suggestions = suggestionList
        notifyDataSetChanged()
    }

    class ViewHolder(itemView: View, val activity: Activity) : RecyclerView.ViewHolder(itemView) {
        val text: MaterialTextView = itemView.suggestion_text
        fun bind(data: String) {
            text.text = data

            itemView.setOnClickListener {
                Log.d("Click",data)
            }
        }
    }
}

ArrayAdapter için bir düzen oluşturma suggestion_textview_item.xml

<?xml version="1.0" encoding="utf-8"?>
<com.google.android.material.textview.MaterialTextView xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/suggestion_text"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="?attr/selectableItemBackground"
    android:clickable="true"
    android:focusable="true"
    android:paddingStart="56dp"
    android:paddingTop="8dp"
    android:paddingEnd="24dp"
    android:paddingBottom="8dp"
    android:textAppearance="@style/TextAppearance.AppCompat.SearchResult.Title"
    android:textColor="@color/textColorPrimary"
    android:textSize="16sp" />

Şimdi bu makalenin ana kısmı, Arayüzde arama sorgulama ve veri kümesi sonuçlarını işleme ve ayrıca bir kullanıcı edittext'de bir duraklama verdiğinde yalnızca veritabanını Sorgulamamız gerekecek şekilde mantık uygulamamız gerekir.

Bunun için Kotlin Coroutines'in delay () fonksiyonunu ve olduğu gibi bazı mantığı kullanıyoruz.

İşte SearchFragment.kt kodu;

class SearchFragment : Fragment() {

    val firestore = Firebase.firestore
    lateinit var searchSuggestionAdapter: ArrayAdapter

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        return inflater.inflate(R.layout.fragment_search, container, false)
    }

    override fun onActivityCreated(savedInstanceState: Bundle?) {
        super.onActivityCreated(savedInstanceState)
        (activity as MainActivity).supportActionBar!!.title = getString(R.string.search)
        (activity as MainActivity).supportActionBar!!.displayOptions = ActionBar.DISPLAY_SHOW_CUSTOM
        searchSuggestionAdapter =
            ArrayAdapter(ArrayList(), requireActivity())
        search_suggestion_recyclerview.apply {
            layoutManager = LinearLayoutManager(requireContext())
            adapter = searchSuggestionAdapter
        }

        val inflate = LayoutInflater.from(requireContext())
            .inflate(R.layout.search_toolbar_custom_view, container, false)
        (activity as MainActivity).supportActionBar!!.customView = inflate

        inflate.search_edittext.addTextChangedListener(object : TextWatcher {
            override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {

            }

            override fun onTextChanged(s: CharSequence?, p1: Int, p2: Int, p3: Int) {
                var searchFor = ""
                val searchText = s.toString().trim()
                if (searchText == searchFor)
                    return
                searchFor = searchText
                GlobalScope.launch(IO) {
                    delay(300)
                    if (searchText != searchFor)
                        [email protected]
                    inflate.search_edittext.text.toString()
                    val suggestionList = ArrayList<String>()
                    val suggestionSnapshot =
                        Firebase.firestore.collection("tags").whereArrayContains(
                            "keywords",
                            searchText.toLowerCase(Locale.ROOT)
                        ).limit(16)
                            .get().await()

                    if (suggestionSnapshot.isEmpty)
                        suggestionList.add("No Search Result Found")

                    suggestionSnapshot.forEach {
                        suggestionList.add(it["name"] as String)
                    }
                    withContext(Main)
                    {
                        searchSuggestionAdapter.setList(suggestionList)
                    }
                }
            }

            override fun afterTextChanged(p0: Editable?) {
                if (TextUtils.isEmpty(p0)) {
                    search_suggestion_recyclerview.visibility = View.GONE
                    category_recyclerview.visibility = View.VISIBLE
                    materialTextView2.visibility = View.VISIBLE
                } else {
                    search_suggestion_recyclerview.visibility = View.VISIBLE
                    category_recyclerview.visibility = View.GONE
                    materialTextView2.visibility = View.GONE
                }
            }
        })
    }
}

SearchFragment.kt için düzen dosyası;

<?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=".ui.SearchFragment">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/search_suggestion_recyclerview"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:visibility="gone"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        tools:listitem="@layout/suggestion_textview_item" />

    <com.google.android.material.textview.MaterialTextView
        android:id="@+id/materialTextView2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_margin="16dp"
        android:text="@string/trending_tags"
        android:textAppearance="@style/TextAppearance.AppCompat.Headline"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/category_recyclerview"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_marginTop="16dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/materialTextView2" />

    <androidx.core.widget.ContentLoadingProgressBar
        android:id="@+id/progress_bar"
        style="@style/Widget.AppCompat.ProgressBar"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:theme="@style/AppTheme.ContentLoadingProgressBar"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>
#android