GK007
GK007

Reputation: 117

Issues implementing search on recycleview kotlin

I'm trying to implement search option in recyclerview.

What I have implemented so far is:

  1. created a search bar as below:

enter image description here

  1. I've applied onCreateOptions as per below in MainActivity:
    class RecyclerListActivity: AppCompatActivity() {
        private lateinit var binding: ActivityMainBinding
        private lateinit var viewModel: PostListViewModel
        private var errorSnackbar: Snackbar? = null


        private var searchView: SearchView? = null

        override fun onCreate(savedInstanceState: Bundle?){
            super.onCreate(savedInstanceState)

            binding = DataBindingUtil.setContentView(this, R.layout.activity_main)
            binding.postList.layoutManager = GridLayoutManager(this, 3, GridLayoutManager.VERTICAL, false)

            viewModel = ViewModelProviders.of(this).get(PostListViewModel::class.java)
            viewModel.errorMessage.observe(this, Observer {
                errorMessage -> if(errorMessage != null) showError(errorMessage) else hideError()
            })
            binding.viewModel = viewModel

        }

        private fun showError(@StringRes errorMessage:Int){
            errorSnackbar = Snackbar.make(binding.root, errorMessage, Snackbar.LENGTH_INDEFINITE)
            errorSnackbar?.setAction(R.string.retry, viewModel.errorClickListener)
            errorSnackbar?.show()
        }

        private fun hideError(){
            errorSnackbar?.dismiss()
        }


        override fun onCreateOptionsMenu(menu: Menu): Boolean {
            menuInflater.inflate(R.menu.menu_main, menu)
            searchView = menu.findItem(R.id.action_search).actionView as SearchView
            searchView!!.maxWidth = Int.MAX_VALUE
            searchView!!.imeOptions = EditorInfo.IME_ACTION_DONE

            // listening to search query text change
            searchView!!.setOnQueryTextListener(object :
                SearchView.OnQueryTextListener {
                override fun onQueryTextSubmit(query: String): Boolean {
                    return false
                }

                override fun onQueryTextChange(query: String): Boolean {
                    return false
                }
            })
            return true
        }
    }
  1. My Adapter class as below:
    class PostListAdapter: RecyclerView.Adapter<PostListAdapter.ViewHolder>(), Filterable {
        private lateinit var postList:List<Data>
        private lateinit var postListFull:List<Data>

        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
            val binding: ListItemBinding = DataBindingUtil.inflate(LayoutInflater.from(parent.context), R.layout.list_item, parent, false)
            return ViewHolder(binding)
        }

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

        override fun getItemCount(): Int {
            return if(::postList.isInitialized) postList.size else 0
        }

        fun updatePostList(postList:List<Data>){
            this.postList = postList
            notifyDataSetChanged()
        }

        class ViewHolder(private val binding: ListItemBinding): RecyclerView.ViewHolder(binding.root){
            private val viewModel = MoviesViewModel()

            fun bind(post:Data){
                viewModel.bind(post)
                binding.viewModel = viewModel
            }

            init {
                binding.root.setOnClickListener {
                    //Toast.makeText(binding.root.context, binding.postTitle.text, Toast.LENGTH_SHORT).show()

                    val intent = Intent(binding.root.context, DetailsActivity::class.java)
                    //intent.putExtra(REPO_NAME, binding.postTitle.text)

                    binding.root.context.startActivity(intent)
                }
            }

        }

        override fun getFilter(): Filter? {
            return searchFilter
        }

        private val searchFilter: Filter = object : Filter() {
            override fun performFiltering(constraint: CharSequence?): FilterResults? {
                val filteredList: MutableList<Data> = ArrayList()
                if (constraint == null || constraint.isEmpty()) {
                    filteredList.addAll(postListFull)
                } else {
                    val filterPattern =
                        constraint.toString().toLowerCase().trim()
                    for (item in postListFull) {
                        if (item.title.toLowerCase().contains(filterPattern) || item.genre.toLowerCase().contains(filterPattern)) {
                            filteredList.add(item)
                        }
                    }
                }
                val results = FilterResults()
                results.values = filteredList
                return results
            }

            override fun publishResults(
                constraint: CharSequence?,
                results: FilterResults
            ) {
                //postList.clear()
                //postList.addAll(results.values as List<*>)
                notifyDataSetChanged()
            }
        }

I have two issues here to resolve it. first one is: getting unresolved reference in these lines (Adapter class). How could I resolve it?

postList.clear()

postList.addAll(results.values as List<*>) 

second one is: how to apply the filter results in adapter as I've used dagger & databinding? I've used following tutorial to create recyclerview: https://proandroiddev.com/mvvm-with-kotlin-android-architecture-components-dagger-2-retrofit-and-rxandroid-1a4ebb38c699

Upvotes: 0

Views: 251

Answers (1)

Divya
Divya

Reputation: 245

 private lateinit var postListFull: ArrayList<Data>= ArrayList()

in the publishResults() method, to store the result in list :

postListFull= results!!.values as ArrayList<Data>
            notifyDataSetChanged()

for your second issue, where do you want to apply the filter results and why?

Upvotes: 1

Related Questions