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:
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 } }
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) } } }
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) } }
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" />