Petros Mosoyan
Petros Mosoyan

Reputation: 258

RecyclerView doesnt keep its scroll position when I submitting same list with different order

I'm using ListAdapter to show my device music on the screen. From option menu user can change the tracks order. When user changes the track order the recycler view shows updated list but also changes its scroll position.

Can you help me to avoid changing scroll position?

Here is my code:

  1. Fragment with recycler view.

    class TabSongsFrg : Fragment() {
    
    private lateinit var binding: FragmentTabSongsBinding
    private lateinit var viewModelFactory: TabSongsViewModelFactory
    private lateinit var viewModel: TabSongsViewModel
    
    private lateinit var tabSongsRva: TabSongsRva
    
     override fun onCreateView(
     inflater: LayoutInflater, container: ViewGroup?,
     savedInstanceState: Bundle?
     ): View {
     try {
         if (!this::binding.isInitialized) {
             binding = FragmentTabSongsBinding.inflate(inflater)
    
             val application = requireNotNull(activity).application
             viewModelFactory = TabSongsViewModelFactory(application, context)
             viewModel =
                 ViewModelProvider(this, viewModelFactory)[TabSongsViewModel::class.java]
    
             binding.lifecycleOwner = this
             binding.viewModel = viewModel
    
             tabSongsRva =
                 TabSongsRva(context, TabSongsRva.OnClickListener { objects ->
    
                 })
             binding.tabSongsRecyclerView.adapter = tabSongsRva
         }
     } catch (e: Exception) {
         firebaseCrashlytics.recordException(e)
     }
    
     return binding.root
     }
    
     private fun prepareToScanMedia() {
     try {
         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
             if (context.checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
                 context.checkPermission()
                 return
             }
         }
    
         val tracksInfo = getAllTracks()
         viewModel.setTracksList(tracksInfo)
     } catch (e: Exception) {
         firebaseCrashlytics.recordException(e)
     }
    }
    
     fun getAllTracks(): ArrayList<TrackInfo> {
     val allTracksInfo: ArrayList<TrackInfo> = ArrayList()
    
     try {
         val selection = MediaStore.Audio.Media.IS_MUSIC + " != 0"
         val sortOrder = getTracksSortOrder()
    
         val music = context.contentResolver.query(
             EXTERNAL_CONTENT_URI,
             projectionMedia,
             selection,
             null,
             sortOrder
         )
    
         while (music!!.moveToNext()) {
             val trackInfo = TrackInfo()
             trackInfo.artist = music.getString(0)
             trackInfo.title = music.getString(1)
             trackInfo.data = music.getString(2)
             trackInfo.displayName = music.getString(3)
             trackInfo.duration = music.getLong(4)
             trackInfo.album = music.getString(5)
             trackInfo.size = music.getLong(6)
             trackInfo.albumId = music.getInt(7)
             trackInfo.artistId = music.getInt(8)
             trackInfo.trackId = music.getInt(9)
             trackInfo.year = music.getInt(10)
             trackInfo.mimeType = music.getString(11)
             trackInfo.photoUri = getTrackAlbumArt(trackInfo.albumId)
    
             allTracksInfo.add(trackInfo)
         }
     } catch (e: Exception) {
         firebaseCrashlytics.recordException(e)
     }
    
     return allTracksInfo
    }
    }
    
  2. ViewModel class

        class TabSongsViewModel(app: Application, private val context: PrepareActivity) :
        AndroidViewModel(app) {
    
        private val _tracksInfo = MutableLiveData<ArrayList<TrackInfo>>()
        val tracksInfo: LiveData<ArrayList<TrackInfo>>
            get() = _tracksInfo
    
    
        fun setTracksList(tracksInfo: ArrayList<TrackInfo>) {
           try {
                 _tracksInfo.value = tracksInfo
           } catch (e: Exception) {
                  firebaseCrashlytics.recordException(e)
            }
          }
        }
    
  3. Adapter

         class TabSongsRva(
         private val onClickListener: OnClickListener
         ) :
         ListAdapter<TrackInfo, TabSongsRva.MarsPropertyViewHolder> 
         (DiffCallback) {
    
           class MarsPropertyViewHolder(
          private var bindingGrid: TrackGridCellBinding
        ) :
     RecyclerView.ViewHolder(bindingGrid.root) {
     fun bind(trackInfo: TrackInfo) {
    
             bindingGrid.trackInfo = trackInfo
             bindingGrid.executePendingBindings()
     }
    }
    
     companion object DiffCallback : DiffUtil.ItemCallback<TrackInfo>() {
     override fun areItemsTheSame(oldItem: TrackInfo, newItem: 
     TrackInfo): Boolean {
         return oldItem.trackId == newItem.trackId
     }
    
     override fun areContentsTheSame(oldItem: TrackInfo, newItem: 
       TrackInfo): Boolean {
         return oldItem.trackId == newItem.trackId
     }
    }
    
     override fun onCreateViewHolder(
     parent: ViewGroup,
     viewType: Int
      ): MarsPropertyViewHolder {
    
     return MarsPropertyViewHolder(
         TrackGridCellBinding.inflate(
             LayoutInflater.from(parent.context),
             parent,
             false
         )
     )
     }
    
    override fun onBindViewHolder(holder: MarsPropertyViewHolder, 
     position: Int) {
     val trackInfo = getItem(position)
    
     holder.itemView.setOnClickListener {
         disableView(holder.itemView)
         val objects = arrayOf<Any>(position, trackInfo)
         onClickListener.onClick(objects)
         }
    
        holder.bind(trackInfo)
       }
    
        class OnClickListener(val clickListener: (objects: Array<Any>) -> 
        Unit)      {
         fun onClick(objects: Array<Any>) = clickListener(objects)
         }
       }
    
  4. Layout File

     <androidx.recyclerview.widget.RecyclerView
             android:id="@+id/tabSongsRecyclerView"
             android:layout_width="match_parent"
             android:layout_height="match_parent"
             android:layoutAnimation="@anim/layout_fall_down"
             android:paddingLeft="3dp"
             android:paddingRight="3dp"
             android:scrollbarSize="4dp"
             android:scrollbarThumbVertical="@drawable/custom_scrollbar"
             android:scrollbars="vertical"
             app:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
             app:layout_behavior="@string/appbar_scrolling_view_behavior"
             app:tabSongsTracksList="@{viewModel.tracksInfo}"
             tools:listitem="@layout/track_list_cell" />
    

Upvotes: 1

Views: 122

Answers (0)

Related Questions