how to implement search viewmodel and show it in recyclerview in kotlin

690 Views Asked by At

I am developing tvshows app where I am implementing following logic user search tvshows and filtered result has to show in recyclerview but I want to implement filtering functionality in viewmodel

how can I achieve that

below interface class

interface ApiInterface {

    @GET("search/shows")
    suspend fun searchShows( @Query("q") query: String): Call<TvMazeResponse>

}

below TvRepository.kt

class TvRepository(private val apiInterface: ApiInterface) {


suspend fun getShows() = apiInterface.searchShows("")

}

below adapter class

class TvAdapter : RecyclerView.Adapter<TvAdapter.ViewHolder>(), Filterable {

    lateinit var tvMazeList: MutableList<TvMazeResponse>
    lateinit var filterResult: ArrayList<TvMazeResponse>


    override fun getItemCount(): Int =
        filterResult.size


    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int) = ViewHolder(
        LayoutInflater.from(parent.context).inflate(
            R.layout.tv_item, parent,
            false
        )
    )

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


    fun addData(list: List<TvMazeResponse>) {
        tvMazeList = list as MutableList<TvMazeResponse>
        filterResult = tvMazeList as ArrayList<TvMazeResponse>
        notifyDataSetChanged()
    }

    override fun getFilter(): Filter {
        return object : Filter() {
            override fun performFiltering(constraint: CharSequence?): FilterResults {
                val charString = constraint?.toString() ?: ""
                if (charString.isEmpty()) filterResult =
                    tvMazeList as ArrayList<TvMazeResponse> else {
                    val filteredList = ArrayList<TvMazeResponse>()
                    tvMazeList
                        .filter {
                            (it.name.contains(constraint!!)) or
                                    (it.language.contains(constraint))

                        }
                        .forEach { filteredList.add(it) }
                    filterResult = filteredList

                }

                return FilterResults().apply { values = filterResult }
            }

            override fun publishResults(constraint: CharSequence?, results: FilterResults?) {
                filterResult = if (results?.values == null)
                    ArrayList()
                else
                    results.values as ArrayList<TvMazeResponse>
                notifyDataSetChanged()
            }

        }
    }


    class ViewHolder(view: View) : RecyclerView.ViewHolder(view) {
        fun bind(result: TvMazeResponse) {
            with(itemView) {
                Picasso.get().load(result.image.medium).into(imageView)
            }
        }
    }


}

below Constants.kt

object Constants {
    const val BASE_URL = "https://api.tvmaze.com/"
}

below TvMazeResponse.kt

data class TvMazeResponse(
    @SerializedName("averageRuntime")
    val averageRuntime: Int,
    @SerializedName("dvdCountry")
    val dvdCountry: Any,
    @SerializedName("externals")
    val externals: Externals,
    @SerializedName("genres")
    val genres: List<String>,
    @SerializedName("id")
    val id: Int,
    @SerializedName("image")
    val image: Image,
    @SerializedName("language")
    val language: String,
    @SerializedName("_links")
    val links: Links,
    @SerializedName("name")
    val name: String,
    @SerializedName("network")
    val network: Network,
    @SerializedName("officialSite")
    val officialSite: String,
    @SerializedName("premiered")
    val premiered: String,
    @SerializedName("rating")
    val rating: Rating,
    @SerializedName("runtime")
    val runtime: Int,
    @SerializedName("schedule")
    val schedule: Schedule,
    @SerializedName("status")
    val status: String,
    @SerializedName("summary")
    val summary: String,
    @SerializedName("type")
    val type: String,
    @SerializedName("updated")
    val updated: Int,
    @SerializedName("url")
    val url: String,
    @SerializedName("webChannel")
    val webChannel: Any,
    @SerializedName("weight")
    val weight: Int
)

below TvViewModel.kt

class TvViewModel(apiInterface: ApiInterface) : ViewModel() {




}

I want to implement filter and search function in viewmodel how can I achieve that any help and tips greatly appreciated

1

There are 1 best solutions below

5
dhiraj uchil On BEST ANSWER

In TvRepository change the getShows function to

suspend fun getShows(searchString:String) = apiInterface.searchShows(searchString)

Then in the ViewModel change the constructor to get an instance of the TVRepository and call API as shown below

class TvViewModel( tvRepository: TvRepository) : ViewModel() {

 fun getShows(searchParameter:String){
   viewModelScope.launch(Dispatchers.IO){
     val response= tvRepository.getShows().awaitResponse()
     if(response.isSuccessful{
       //api success you can get result from response.body

     }
     else{
       //api failed
     }
   }
}



}