Как реализовать serch в представлении recycler для данных firestore?

#android #firebase #kotlin #google-cloud-firestore

#Android #firebase #kotlin #google-облако-firestore

Вопрос:

Я хочу реализовать поиск в моем recyclerview. Данные, которые я извлекаю, взяты из firebase (firestore). Когда я нажимаю на значок поиска и набираю любой текст, мое приложение выходит из строя, и я не могу понять, в чем может быть причина. Кто-нибудь может сказать мне, что не так с моим кодом?

 class ActivityStudentList : AppCompatActivity() {
private lateinit var studentRecyclerView: RecyclerView
private lateinit var recyclerViewAdapter: RecyclerViewAdapter
private val db = FirebaseFirestore.getInstance()
private lateinit var studentArrayList: ArrayList<StudentRecyclerViewDataClass>

private lateinit var editStudentFab: ExtendedFloatingActionButton
private lateinit var addStudentFab: ExtendedFloatingActionButton
private lateinit var removeStudentFab: ExtendedFloatingActionButton

private lateinit var tempArrayList: ArrayList<StudentRecyclerViewDataClass>
private lateinit var newArrayList: ArrayList<StudentRecyclerViewDataClass>

private var clicked = false
private lateinit var obstructor: RelativeLayout

private val fromBottom: Animation by lazy { AnimationUtils.loadAnimation(this,R.anim.from_bottom_anim) }
private val toBottom: Animation by lazy { AnimationUtils.loadAnimation(this,R.anim.to_bottom_anim) }

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_student_list)

    supportActionBar?.setDisplayHomeAsUpEnabled(false)
    actionBar?.setDisplayShowTitleEnabled(false)
    supportActionBar?.setDisplayShowTitleEnabled(false)

    editStudentFab = findViewById(R.id.editStudentFab)
    addStudentFab = findViewById(R.id.addStudentFab)
    removeStudentFab = findViewById(R.id.removeStudentFab)

    obstructor = findViewById(R.id.obstructor)

    studentRecyclerView = findViewById(R.id.studentRecyclerView)
    studentRecyclerView.layoutManager = LinearLayoutManager(this)
    studentRecyclerView.setHasFixedSize(true)

    studentArrayList = arrayListOf<StudentRecyclerViewDataClass>()
    recyclerViewAdapter = RecyclerViewAdapter(studentArrayList)

    studentRecyclerView.adapter = recyclerViewAdapter

    studentRecyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() {
        override fun onScrolled(studentRecyclerView: RecyclerView, dx: Int, dy: Int) {
            if (dy > 0) editStudentFab.hide() else if (dy < 0) editStudentFab.show()
        }
    })

    getStudentData()

    editStudentFab.setOnClickListener {
        onEditButtonClicked()
    }
    addStudentFab.setOnClickListener {
        startActivity(Intent(this,ActivityAddStudent::class.java))
    }
    removeStudentFab.setOnClickListener {
        startActivity(Intent(this,ActivityAddStudent::class.java))
    }

}

override fun onCreateOptionsMenu(menu: Menu?): Boolean {
    menuInflater.inflate(R.menu.student_recycler_view_search, menu)

    val search = menu?.findItem(R.id.student_recycler_view_search)
    val searchView = search?.actionView as? SearchView
    searchView?.isSubmitButtonEnabled = true
    searchView?.setOnQueryTextListener(object: SearchView.OnQueryTextListener{
        override fun onQueryTextSubmit(query: String?): Boolean {
            TODO("Not yet implemented")
        }

        @SuppressLint("NotifyDataSetChanged")
        override fun onQueryTextChange(newText: String?): Boolean {
            tempArrayList.clear()
            val searchText = newText!!.toLowerCase(Locale.getDefault())
            if(searchText.isNotEmpty()){
                newArrayList.forEach{
                    if(it.Name!!.toLowerCase(Locale.getDefault()).contains(searchText)){
                        tempArrayList.add(it)
                    }
                }
                studentRecyclerView.adapter!!.notifyDataSetChanged()
            }else{
                tempArrayList.clear()
                tempArrayList.addAll(newArrayList)
                studentRecyclerView.adapter!!.notifyDataSetChanged()
            }
            return false
        }

    })

    return super.onCreateOptionsMenu(menu)
}

private fun onEditButtonClicked() {
    setVisibility(clicked)
    setAnimation(clicked)
    clicked = !clicked
}

@SuppressLint("SetTextI18n")
private fun setAnimation(clicked: Boolean) {
    obstructor = findViewById(R.id.obstructor)
    addStudentFab = findViewById(R.id.addStudentFab)
    removeStudentFab = findViewById(R.id.removeStudentFab)
    editStudentFab = findViewById(R.id.editStudentFab)
    if(!clicked){
        obstructor.visibility = View.VISIBLE
        editStudentFab.text = "Close"
        editStudentFab.setIconResource(R.drawable.ic_outline_close_24)
        addStudentFab.startAnimation(fromBottom)
        removeStudentFab.startAnimation(fromBottom)
    }else{
        obstructor.visibility = View.INVISIBLE
        editStudentFab.text = "Edit List"
        editStudentFab.setIconResource(R.drawable.ic_outline_edit_24)
        addStudentFab.startAnimation(toBottom)
        removeStudentFab.startAnimation(toBottom)
    }
}

private fun setVisibility(clicked: Boolean) {
    addStudentFab = findViewById(R.id.addStudentFab)
    removeStudentFab = findViewById(R.id.removeStudentFab)
    if(!clicked){
        addStudentFab.visibility = View.VISIBLE
        removeStudentFab.visibility = View.VISIBLE
    }else{
        addStudentFab.visibility = View.INVISIBLE
        removeStudentFab.visibility = View.INVISIBLE
    }
}

private fun getStudentData() {
    
    db.collection("StudentInfo").addSnapshotListener(object: EventListener<QuerySnapshot>{
        @SuppressLint("NotifyDataSetChanged")
        override fun onEvent(value: QuerySnapshot?, error: FirebaseFirestoreException?) {
            if(error != null){
                Log.e("Firestore Error",error.message.toString())
                return
            }

            for(dc : DocumentChange in value?.documentChanges!!){
                if(dc.type == DocumentChange.Type.ADDED){
                    studentArrayList.add(dc.document.toObject(StudentRecyclerViewDataClass::class.java))
                }
            }
            recyclerViewAdapter.notifyDataSetChanged()
        }

    })
}
}
 

Код адаптера RecyclerView:

 class RecyclerViewAdapter(private var studentList : ArrayList<StudentRecyclerViewDataClass>) : RecyclerView.Adapter<RecyclerViewAdapter.RecyclerViewHolder>() {

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerViewHolder {
    val itemView = LayoutInflater.from(parent.context).inflate(R.layout.recycler_view_student_list_item,parent,false)
    return RecyclerViewHolder(itemView)
}

override fun onBindViewHolder(holder: RecyclerViewHolder, position: Int) {
    val currentItem = studentList[position]
    holder.name.text = currentItem.Name
    holder.SRN.text = currentItem.SRN
    holder.phone.text = currentItem.Phone
    holder.age.text = currentItem.Age
}

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

class RecyclerViewHolder(itemView : View ) : RecyclerView.ViewHolder(itemView){
    val name : TextView = itemView.findViewById(R.id.tv_name)
    val SRN : TextView = itemView.findViewById(R.id.tv_srn)
    val phone : TextView = itemView.findViewById(R.id.tv_phone)
    val age : TextView = itemView.findViewById(R.id.tv_age)
}
 

}

Комментарии:

1. Пожалуйста, используйте android-studio тег только для вопросов о самой IDE Android Studio. Для вопросов о программировании на Android в целом используйте android тег.

2. Если ваше приложение выходит из строя, оно записывает сообщение об ошибке и трассировку стека в свой вывод logcat. Пожалуйста, найдите их и добавьте к своему вопросу (прямо под ним есть ссылка). edit

3. Пожалуйста, отредактируйте свой вопрос и добавьте информацию, которую просил Фрэнк ван Пуффелен, а также, пожалуйста, ответьте с помощью @.

4. Кроме того, я думаю, что эта статья, как фильтровать данные Firestore дешевле? может помочь.