[android/kotlin] firebase-firestore query 검색기능 만들기

남윤희·2023년 10월 23일
0

kotlin

목록 보기
20/25

firebase공식문서참고

이전 게시글에 firestore에 업로드 및 recyclerView로 가져오기를 포스팅 했었다.
공식문서를 참고하여 Search기능을 만들어보자.

db.collection("cities")
    .whereEqualTo("capital", true)
    .get()
    .addOnSuccessListener { documents ->
        for (document in documents) {
            Log.d(TAG, "${document.id} => ${document.data}")
        }
    }
    .addOnFailureListener { exception ->
        Log.w(TAG, "Error getting documents: ", exception)
    }

공식 문서에 나와있는 예제이다. 저대로 따라하면 된다.

Fragment와 xml파일을 먼저 만들어준다.

xml

<?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"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="@color/white"
    tools:context=".home.Search.SeachFragment">


    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">


        <EditText
            android:id="@+id/editTextText"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:ems="10"
            android:inputType="text"
            android:text="Name"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent" />

        <androidx.recyclerview.widget.RecyclerView
            android:id="@+id/searchRecycler"
            android:layout_width="409dp"
            android:layout_height="671dp"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/editTextText" />
    </androidx.constraintlayout.widget.ConstraintLayout>
</FrameLayout>
  • 단순히 EditText와 title이 같은 값을 검색해 뿌려줄 RecyclerView를 배치해뒀다.

Fragment

package com.dreamteam.sharedream.home.Search

import android.content.Context
import android.os.Bundle
import android.text.Editable
import android.text.TextWatcher
import android.util.Log
import androidx.fragment.app.Fragment
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.LinearLayoutManager
import com.dreamteam.sharedream.databinding.FragmentSeachBinding
import com.dreamteam.sharedream.model.PostData
import com.google.firebase.firestore.FirebaseFirestore


class SeachFragment : Fragment() {

    private lateinit var searchadapter: SeachAdapter
    private lateinit var binding: FragmentSeachBinding
    private lateinit var mContext: Context

    private val firestore = FirebaseFirestore.getInstance()


    override fun onAttach(context: Context) {
        super.onAttach(context)
        mContext = context
    }

    override fun onCreateView(
        inflater: LayoutInflater, container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        binding = FragmentSeachBinding.inflate(inflater, container, false)


        return binding.root
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)

        //어댑터 초기화!해야됨!

        searchadapter = SeachAdapter(mContext)
        val searchEdit = binding.editTextText

        binding.searchRecycler.layoutManager =
            LinearLayoutManager(mContext, LinearLayoutManager.VERTICAL, false)
        binding.searchRecycler.adapter = searchadapter

        // 검색어 필수 메서드
        searchEdit.addTextChangedListener(object : TextWatcher {
            override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
            }

            override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
            }

            override fun afterTextChanged(p0: Editable?) {
                //검색어 입력 후 searchTitle 실행
                val query = p0.toString()
                if (query.isNotEmpty()) {
                    searchTitle(query)
                    Log.d("nyh", "afterTextChanged: $p0 // $query ")
                } else {
                    Log.d("nyh", "afterTextChanged else: $p0 // $query")
                }
            }
        })
    }

    private fun searchTitle(title: String) {
        val postCollection = firestore.collection("Post")
        //query 객체 만들고 get으로 가져오기
        postCollection.whereEqualTo("title", title)
            .get()
            .addOnSuccessListener { querySnapshot ->
                val searchList = mutableListOf<PostData>()

                //for문으로 data를 searchList에 넣어주고 adapter로 전달하기

                for (i in querySnapshot.documents) {
                    val data = i.toObject(PostData::class.java)
                    data?.let {
                        searchList.add(it)
                        Log.d("nyh", "searchTitle: $searchList")
                    }
                }
                searchadapter.setData(searchList)
                val startPosition = searchList.size
                searchadapter.notifyItemRangeInserted(startPosition, searchList.size)
            }.addOnFailureListener { exception ->
                Log.d("nyh", "searchTitle fail : $exception")
            }
    }

}
  • searchTitle 함수를 생성해서 위 공식문서 대로 whereEqualTo를 사용하여 데이터를 정렬한다.

recyclerView에 출력 할 adapter를 작성한다.

adatper

package com.dreamteam.sharedream.home.Search

import android.util.Log
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView
import com.bumptech.glide.Glide
import com.dreamteam.sharedream.databinding.WriteItemBinding
import com.dreamteam.sharedream.model.PostData
import android.content.Context
import com.google.firebase.ktx.Firebase
import com.google.firebase.storage.ktx.storage

class SeachAdapter(private val context: Context) :
    RecyclerView.Adapter<RecyclerView.ViewHolder>() {

    private var searchDataItem: List<PostData> = ArrayList()


    // 외부에서 데이터 설정하는 함수
    fun setData(data: List<PostData>){
        searchDataItem = ArrayList(data)
        Log.d("nyh", "setDataSearchAdpater: $data")
    }
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
        val inflater = LayoutInflater.from(parent.context)
        val binding = WriteItemBinding.inflate(inflater, parent, false)
        return SearchHolder(binding)
    }

    override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {

        val searchItem = searchDataItem[position]
        val searchHolder = holder as SeachAdapter.SearchHolder
        val storage = Firebase.storage
        val fileName = searchItem.image
        val storageRef = storage.getReference("image").child(fileName)
        val downloadTask = storageRef.downloadUrl

        downloadTask.addOnSuccessListener { uri ->

            Glide.with(context)
                .load(uri)
                .into(searchHolder.image)
        }.addOnFailureListener {
            Log.e("HomeAdpate", "nyh Glade imageDownload fail homeitem.image =  ${searchItem.image}")
            Log.e("HomeAdpate", "nyh Glade imageDownload fail it =  $it")
            Log.d("nyh", "onBindViewHolder: $storageRef")
            Log.d("nyh", "onBindViewHolder: $fileName")
        }

        searchHolder.title.text = searchItem.title
        searchHolder.subtitle.text = searchItem.mainText
        searchHolder.category.text = searchItem.category
        searchHolder.value.text = searchItem.value.toString()
        Log.d("nyh", "onBindViewHolder: $searchItem")
    }

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

    inner class SearchHolder(val binding: WriteItemBinding) :
        RecyclerView.ViewHolder(binding.root) {
        val title = binding.writeTittle
        val subtitle = binding.writeSubtittle
        val value = binding.writePrice
        val category = binding.writeCategory
        val image = binding.writeImage
    }
}

😁완-성🙄

profile
안드로이드 주니어 개발자

0개의 댓글