Home > database >  RecyclerView recreated on screen rotation
RecyclerView recreated on screen rotation

Time:10-30

`

class MoviesFragment : Fragment() {

    private var viewModel: MoviesViewModel? = null
    private var adapter = MoviesAdapter()
    private lateinit var binding : FragmentMoviesBinding

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

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

    private fun recyclerViewInit() {
        val recyclerView = binding.recyclerView
        recyclerView.adapter = adapter
        recycler_view.layoutManager = LinearLayoutManager(requireContext())
    }

    private fun viewModelInit() {
        viewModel = ViewModelProvider(this)[MoviesViewModel::class.java]
        viewModel!!.getPageOfMovies()
        viewModel!!.myResponse.observe(viewLifecycleOwner) { response ->
            if (response.isSuccessful) {
                response.body()?.let { movies ->
                    adapter.setData(movies) }
            } else {
                Toast.makeText(requireContext(), response.code(), Toast.LENGTH_SHORT).show()
            }

        }
    }
}

`

`

class MoviesViewModel(application: Application) : AndroidViewModel(application) {

    private val repository = MoviesRepository()
    val myResponse: MutableLiveData<Response<MovieResponse>> = MutableLiveData()

    fun getPageOfMovies() {
        viewModelScope.launch {
            val response = repository.getPageOfMovies()
            myResponse.value = response
        }
    }
}

`

`

class MoviesAdapter : RecyclerView.Adapter<MoviesAdapter.ViewHolder>() {
    private var moviesList = MovieResponse(0, emptyList(), 0, 0)

    inner class ViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView)

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        return ViewHolder(
            LayoutInflater.from(parent.context).inflate(
                R.layout.movies_recyclerview_item, parent, false
            )
        )
    }

    override fun getItemCount(): Int = moviesList.results.size

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        Glide.with(holder.itemView.context)
            .load(Uri.parse("$BASE_URI_FOR_IMAGES${moviesList.results[position].posterPath}"))
            .centerCrop()
            .into(holder.itemView.poster_imageview)
        holder.itemView.title.text = moviesList.results[position].title
        holder.itemView.overview.text = moviesList.results[position].overview
        holder.itemView.release_date.text = moviesList.results[position].releaseDate
    }

    @SuppressLint("NotifyDataSetChanged")
    fun setData(movies: MovieResponse) {
        moviesList = movies
        notifyDataSetChanged()
    }

    companion object{
        const val BASE_URI_FOR_IMAGES = "https://www.themoviedb.org/t/p/w220_and_h330_face/"
    }
}

`

`

class MoviesRepository {
    suspend fun getPageOfMovies(): Response<MovieResponse> {
        return MoviesClient.api.getFirstPageOfPopularMovies()
    }
}

`

When the screen is rotated in the RecyclerView, the data is loaded again on top of the new ones, that is, the list is on top of the list. What could be the problem? That is, I can scroll and view my data, but in the background I see my old list.

I tried to find where I recreate the RecyclerView, but apparently everything should work.

CodePudding user response:

Screen rotation and other config changes recreate your activity by default. The recreated activity will restore its fragments. You should only add the fragment anew when the activity is starting fresh and is not being recreated, that is, the savedInstanceState bundle is null. Otherwise you'd be adding a new fragment on top of the restored one(s).

  • Related