'items on my list doesn't get cleared new items add on the bottom

I'm doing a api request with paramether from a edittext the items comes from api being added to list but I wanna clear the old list and create a new list for this items how can I do that?

when I try differ.currentList.clear() is crashes the app and I can't think of anything else

here is my MainActivity

private lateinit var viewModel: MoviesViewModel
private lateinit var binding: ActivityMainBinding
lateinit var moviesAdapter: MoviesAdapter
var movieName: String = "fast"

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    binding = ActivityMainBinding.inflate(layoutInflater)
    setContentView(binding.root)
    binding.moviesRecyclerView.layoutManager = LinearLayoutManager(this)
    val viewModelFactory = MoviesViewModelFactory(MoviesRepository())
    viewModel = ViewModelProvider(this, viewModelFactory).get(MoviesViewModel::class.java)
    observeData()
    setUpRecyclerView()
    viewModel.getSearchedMovie(movieName)
    searchMovie()
}

private fun observeData() {
    viewModel.searchedMovie.observe(this, Observer { response ->
        when (response) {
            is Resource.Success -> {
                hideProgressBar()
                response.data?.let { movieResponse ->
                    moviesAdapter.differ.submitList(movieResponse.search.toList())
                }
                if (isLastPage) {
                    binding.moviesRecyclerView.setPadding(0, 0, 0, 0)
                }
            }
            is Resource.Error -> {
                hideProgressBar()
                Toast.makeText(this, "No Movie Found", Toast.LENGTH_SHORT).show()
            }
            is Resource.Loading -> {
                showProgressBar()
            }
        }
    })
}

private fun searchMovie() {
    binding.movieNameEditTextView.setOnKeyListener(View.OnKeyListener { view, i, keyEvent ->
        if (keyEvent.action == KeyEvent.ACTION_DOWN && i == KeyEvent.KEYCODE_ENTER) {
            movieName = binding.movieNameEditTextView.text.toString()
            if (movieName != null) {
                if (movieName.length > 2) {
                    closeKeyboard()
                    viewModel.resetMovies()
                    viewModel.getSearchedMovie(movieName)
                } else {
                    Toast.makeText(this, "Please Try Longer Movie Name", Toast.LENGTH_SHORT)
                        .show()
                }
            } else {
                Toast.makeText(this, "Please Enter Movie Name", Toast.LENGTH_SHORT).show()
            }
        }
        return@OnKeyListener false
    })
}

private fun setUpRecyclerView() {
    moviesAdapter = MoviesAdapter()
    with(binding.moviesRecyclerView) {
        adapter = moviesAdapter
        addOnScrollListener(scrollListener)
    }
}

and my Adapter

class MoviesAdapter() :
RecyclerView.Adapter<MoviesAdapter.RowHolder>() {

private val differCallback = object : DiffUtil.ItemCallback<Search>() {
    override fun areItemsTheSame(oldItem: Search, newItem: Search): Boolean {
        return oldItem.poster == newItem.poster
    }

    override fun areContentsTheSame(oldItem: Search, newItem: Search): Boolean {
        return oldItem == newItem
    }
}

val differ = AsyncListDiffer(this, differCallback)

inner class RowHolder(val binding: MoviesRowBinding) : RecyclerView.ViewHolder(binding.root) {

}

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RowHolder {
    val binding = MoviesRowBinding.inflate(LayoutInflater.from(parent.context), parent, false)
    return RowHolder(binding)
}

override fun onBindViewHolder(holder: RowHolder, position: Int) {
    val movie = differ.currentList[position]
    holder.binding.apply {
        Glide.with(movieRowImageView.context).load(movie.poster)
            .into(movieRowImageView)
        movieRowTitleTextView.text = movie.title
        movieRowImdbIDTextView.text = movie.imdbID
        movieRowYearTextView.text = movie.year

    }
}

override fun getItemCount(): Int = differ.currentList.size


Solution 1:[1]

Pretty unusual use of DiffUtil. I would suggest you to use ListAdapater here.

Move you DiffUtil.ItemCallback to the separate class:

class MoviesCallback : DiffUtil.ItemCallback<Search>() {
    override fun areItemsTheSame(oldItem: Search, newItem: Search): Boolean {
        return oldItem.poster == newItem.poster
    }

    override fun areContentsTheSame(oldItem: Search, newItem: Search): Boolean {
        return oldItem == newItem
    }
}

Next, extend your adapter from ListAdapter like this:

class MoviesAdapter() : ListAdapter<Search, MoviesAdapter.RowHolder>(MoviesCallback()) {

    inner class RowHolder(val binding: MoviesRowBinding) : RecyclerView.ViewHolder(binding.root) {}

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RowHolder {
        val binding = MoviesRowBinding.inflate(LayoutInflater.from(parent.context), parent, false)
        return RowHolder(binding)
    }

    override fun onBindViewHolder(holder: RowHolder, position: Int) {
        val movie = currentList[position]
        holder.binding.apply {
            Glide.with(movieRowImageView.context).load(movie.poster).into(movieRowImageView)
            movieRowTitleTextView.text = movie.title
            movieRowImdbIDTextView.text = movie.imdbID
            movieRowYearTextView.text = movie.year
        }
    }
}

Now you can submit your lists directly to the adapter

moviesAdapter.submitList(movieResponse.search.toList())

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1