skip to Main Content

I have a music list obtained from:

MusicDatabase.kt

override fun getContentProviderValue(): MutableList<Songs> {

    val songList =  mutableListOf<Songs>()
    val collection = sdk29AndUp {
        MediaStore.Audio.Media.getContentUri(MediaStore.VOLUME_EXTERNAL)
    } ?:  MediaStore.Audio.Media.EXTERNAL_CONTENT_URI

    //Get songs from provider
    context.contentResolver.query(
        collection,
        projection,
        selection,
        null,
        PreferenceHelper.storeAllSongsSortOrder //Sort order.
    ).use { cursor -> 
    ............
 }
}

Using SharedPreference, I am storing and obtaining sort order like this:

PreferenceHelper.kt

//store allSongs sort order
var storeAllSongsSortOrder: String?
    get() = preferences.getString(allSongSortOrder.first, allSongSortOrder.second)
    set(value) = preferences.edit {
        if (value != null) {
          it.putString(allSongSortOrder.first, value)
    }
}

I obtain the songList like this:

SongsFragment.kt

 mainViewModel.mediaItems.observe(viewLifecycleOwner){ result->
 when(result.status) {
 Status.SUCCESS -> {
 result.data?.let { songs ->        
 allSongsAdapter.songs = songs
 ........
 }

In my songs fragment, when user clicks "Sort", a dropdown will appear with 2 options:

  1. Sort by name
  2. Sort by date

When user clicks sort by name, I do this:

SongsFragment.kt

PreferenceHelper.storeAllSongsSortOrder = Constants.SORT_TITLE
binding.rcvAllSongs.invalidate()
allSongsAdapter.notifyDataSetChanged()

When user clicks sort by date, I do this:

 PreferenceHelper.storeAllSongsSortOrder = Constants.SORT_LAST_ADDED
 binding.rcvAllSongs.invalidate()
 allSongsAdapter.notifyDataSetChanged()

PROBLEM: The list is not updating real time as I select, I have to close the app and open before my list gets the selected sort order.

I want – when I click e.g "Sort by date" – The list should update immediately and display songs based on date added.

2

Answers


  1. You are not assigning the updated list to allSongsAdapter after user presses a button.

     PreferenceHelper.storeAllSongsSortOrder = Constants.SORT_LAST_ADDED | Constants.SORT_TITLE
     binding.rcvAllSongs.invalidate()
     allSongsAdapter.songs = songs         // You have to update the Adapter data set with sorted list
     allSongsAdapter.notifyDataSetChanged()
    

    So either you make sure that mainViewModel.mediaItems.observe is invoked when user selects sort, which is only possible if MusicTable is updated or you save the list received in mainViewModel.mediaItems.observe in a variable and then sort and reassign it when user wants to sort the list

    Login or Signup to reply.
  2. You can propably do something like this:

    class YourFragment : Fragment {
     
      private val allSongsAdapter = SongsAdapter()
    
      override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
      ): View {
        //init your views, bindins, view model and your recycler view adapter
        //...
        binding.recyclerView.adapter = allSongsAdapter
      }
      
      //...
      override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        mainViewModel.songList.observe(viewLifecycleOwner, { result ->
          when (result.status) {
            Status.SUCCESS -> {
              allSongsAdapter.updateList(result.data)
            }
          }
        })
        
        //or whatever you have on your UI to change your filter
        binding.sortFilter.setOnClickListener { filter ->
          mainViewModel.updateSortFilter(filter)
        }
        
        //....
        viewModel.initList()
      }
    }
    
    class YourViewModel() : ViewModel() {
    
      private var _unsortedSongList: List<String> = emptyList()
      
      private val _songList = MutableLiveData<Songs>()
      val songList: LiveData<Songs> = _songList
    
      private lateinit var musicDatabase: MusicDatabase
    
      init {
        musicDatabase = //get the dependency or inject it from constructor
        _unsortedSongList = musicDatabase.getContentProviderValue()
      }
    
      fun initList() {
        _songList.value = sortSongs(PreferencesHelper.storeAllSongsSortOrder)
      }
    
      fun updateSortFilter(sortFilter: String) {
        PreferencesHelper.storeAllSongsSortOrder = sortFilter
        _songList.value = sortSongs(sortFilter)
      }
    
      private fun sortSongs(sortFilter: String): List<Songs> {
        var sortedList: List<Songs> = emptyList()
        switch (sortFilter) {
          Constants.SORT_LAST_ADDED -> {
            sortedList = _unsortedSongList.sortedBy { it.createdMillis }
          }
          Constants.SORT_LAST_ADDED -> {
            sortedList = _unsortedSongList.sortedBy { it.name }
          }
        }
        return sortedList
      }
    
    
    }
    
    class SongsAdapter : RecyclerView.Adapter<SongItemAdapter.ViewHolder> {
      private val songsList = mutableListOf<Songs>()
    
      fun updateList(list: List<Songs>) {
        songsList.clear()
        songsList.addAll(list)
        notifyDataSetChanged()
      }
    
      //.... the rest of your adapter and viewholder
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search