Android Navigation code refactor

This commit is contained in:
Hemanth S 2020-08-13 13:54:36 +05:30
parent 9552e617b5
commit 23f4fee872
81 changed files with 1235 additions and 919 deletions

View file

@ -0,0 +1,130 @@
package code.name.monkey.retromusic.fragments
import android.os.Bundle
import android.view.View
import android.widget.ImageView
import androidx.navigation.fragment.navArgs
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager
import code.name.monkey.retromusic.*
import code.name.monkey.retromusic.adapter.album.AlbumAdapter
import code.name.monkey.retromusic.adapter.artist.ArtistAdapter
import code.name.monkey.retromusic.adapter.song.SongAdapter
import code.name.monkey.retromusic.fragments.albums.AlbumClickListener
import code.name.monkey.retromusic.fragments.artists.ArtistClickListener
import code.name.monkey.retromusic.fragments.base.AbsMainActivityFragment
import code.name.monkey.retromusic.model.Album
import code.name.monkey.retromusic.model.Artist
import code.name.monkey.retromusic.model.Song
import code.name.monkey.retromusic.providers.RepositoryImpl
import kotlinx.android.synthetic.main.fragment_playlist_detail.*
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers.IO
import kotlinx.coroutines.Dispatchers.Main
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import org.koin.android.ext.android.inject
class DetailListFragment : AbsMainActivityFragment(R.layout.fragment_playlist_detail),
ArtistClickListener, AlbumClickListener {
private val args by navArgs<DetailListFragmentArgs>()
private val repository by inject<RepositoryImpl>()
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
mainActivity.setSupportActionBar(toolbar)
mainActivity.hideBottomBarVisibility(false)
when (args.type) {
TOP_ARTISTS -> {
loadArtists(R.string.top_artists, TOP_ARTISTS)
}
RECENT_ARTISTS -> {
loadArtists(R.string.recent_artists, RECENT_ARTISTS)
}
TOP_ALBUMS -> {
loadAlbums(R.string.top_albums, TOP_ALBUMS)
}
RECENT_ALBUMS -> {
loadAlbums(R.string.recent_albums, RECENT_ALBUMS)
}
FAVOURITES -> {
loadFavorite()
}
}
}
private fun loadFavorite() {
toolbar.setTitle(R.string.favorites)
CoroutineScope(IO).launch {
val songs = repository.favoritePlaylistHome()
withContext(Main) {
recyclerView.apply {
adapter = SongAdapter(
requireActivity(),
songs.arrayList as MutableList<Song>,
R.layout.item_list, null
)
layoutManager = linearLayoutManager()
}
}
}
}
private fun loadArtists(title: Int, type: Int) {
toolbar.setTitle(title)
CoroutineScope(IO).launch {
val artists =
if (type == TOP_ARTISTS) repository.topArtists() else repository.recentArtists()
withContext(Main) {
recyclerView.apply {
adapter = artistAdapter(artists)
layoutManager = gridLayoutManager()
}
}
}
}
private fun loadAlbums(title: Int, type: Int) {
toolbar.setTitle(title)
CoroutineScope(IO).launch {
val albums =
if (type == TOP_ALBUMS) repository.topAlbums() else repository.recentAlbums()
withContext(Main) {
recyclerView.apply {
adapter = albumAdapter(albums)
layoutManager = gridLayoutManager()
}
}
}
}
private fun artistAdapter(artists: List<Artist>): ArtistAdapter = ArtistAdapter(
requireActivity(),
artists,
R.layout.item_grid_circle,
null, this@DetailListFragment
)
private fun albumAdapter(albums: List<Album>): AlbumAdapter = AlbumAdapter(
requireActivity(),
albums,
R.layout.item_grid,
null, this@DetailListFragment
)
private fun linearLayoutManager(): LinearLayoutManager =
LinearLayoutManager(requireContext(), LinearLayoutManager.VERTICAL, false)
private fun gridLayoutManager(): GridLayoutManager =
GridLayoutManager(requireContext(), 2, GridLayoutManager.VERTICAL, false)
override fun onArtist(artistId: Int, imageView: ImageView) {
}
override fun onAlbumClick(albumId: Int, view: View) {
}
}

View file

@ -4,7 +4,6 @@ import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import code.name.monkey.retromusic.adapter.HomeAdapter
import code.name.monkey.retromusic.fragments.ReloadType.*
import code.name.monkey.retromusic.interfaces.MusicServiceEventListener
import code.name.monkey.retromusic.model.*
@ -18,13 +17,13 @@ class LibraryViewModel(
private val repository: RepositoryImpl
) : ViewModel(), MusicServiceEventListener {
private val paletteColor = MutableLiveData<Int>()
private val albums = MutableLiveData<List<Album>>()
private val songs = MutableLiveData<List<Song>>()
private val artists = MutableLiveData<List<Artist>>()
private val playlists = MutableLiveData<List<Playlist>>()
private val genres = MutableLiveData<List<Genre>>()
private val home = MutableLiveData<List<Home>>()
private val paletteColor = MutableLiveData<Int>()
val paletteColorLiveData: LiveData<Int> = paletteColor
val homeLiveData: LiveData<List<Home>> = home
@ -46,38 +45,14 @@ class LibraryViewModel(
artists.value = loadArtists.await()
playlists.value = loadPlaylists.await()
genres.value = loadGenres.await()
loadHomeSections()
home.value = loadHome.await()
}
private fun loadHomeSections() = viewModelScope.launch {
val list = mutableListOf<Home>()
val result = listOf(
repository.topArtists(),
repository.topAlbums(),
repository.recentArtists(),
repository.recentAlbums()/*,
repository.suggestions(),
repository.favoritePlaylist(),
repository.homeGenres()*/
)
result.forEach {
if (it != null && it.arrayList.isNotEmpty()) {
if (it.homeSection == HomeAdapter.SUGGESTIONS) {
if (it.arrayList.size > 9) {
list.add(it)
}
} else {
list.add(it)
}
}
}
home.value = list
}
private val loadHome: Deferred<List<Home>>
get() = viewModelScope.async { repository.homeSections() }
private val loadSongs: Deferred<List<Song>>
get() = viewModelScope.async(IO) {
repository.allSongs()
}
get() = viewModelScope.async(IO) { repository.allSongs() }
private val loadAlbums: Deferred<List<Album>>
get() = viewModelScope.async(IO) {
@ -99,6 +74,7 @@ class LibraryViewModel(
repository.allGenres()
}
fun forceReload(reloadType: ReloadType) = viewModelScope.launch {
when (reloadType) {
Songs -> songs.value = loadSongs.await()
@ -114,15 +90,37 @@ class LibraryViewModel(
override fun onMediaStoreChanged() {
loadLibraryContent()
println("onMediaStoreChanged")
}
override fun onServiceConnected() {}
override fun onServiceDisconnected() {}
override fun onQueueChanged() {}
override fun onPlayingMetaChanged() {}
override fun onPlayStateChanged() {}
override fun onRepeatModeChanged() {}
override fun onShuffleModeChanged() {}
override fun onServiceConnected() {
println("onServiceConnected")
}
override fun onServiceDisconnected() {
println("onServiceDisconnected")
}
override fun onQueueChanged() {
println("onQueueChanged")
}
override fun onPlayingMetaChanged() {
println("onPlayingMetaChanged")
}
override fun onPlayStateChanged() {
println("onPlayStateChanged")
}
override fun onRepeatModeChanged() {
println("onRepeatModeChanged")
}
override fun onShuffleModeChanged() {
println("onShuffleModeChanged")
}
}

View file

@ -6,13 +6,13 @@ import android.net.Uri
import android.os.Bundle
import android.view.View
import androidx.core.app.ShareCompat
import androidx.fragment.app.Fragment
import androidx.recyclerview.widget.DefaultItemAnimator
import androidx.recyclerview.widget.LinearLayoutManager
import code.name.monkey.retromusic.App
import code.name.monkey.retromusic.Constants
import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.adapter.ContributorAdapter
import code.name.monkey.retromusic.fragments.base.AbsMainActivityFragment
import code.name.monkey.retromusic.model.Contributor
import code.name.monkey.retromusic.util.NavigationUtil
import com.google.gson.Gson
@ -24,7 +24,7 @@ import kotlinx.android.synthetic.main.card_social.*
import java.io.IOException
import java.nio.charset.StandardCharsets
class AboutFragment : AbsMainActivityFragment(R.layout.fragment_about), View.OnClickListener {
class AboutFragment : Fragment(R.layout.fragment_about), View.OnClickListener {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
version.setSummary(getAppVersion())

View file

@ -62,17 +62,15 @@ class AlbumDetailsFragment : AbsMainActivityFragment(R.layout.fragment_album_det
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
setHasOptionsMenu(true)
mainActivity.hideBottomBarVisibility(false)
mainActivity.addMusicServiceEventListener(detailsViewModel)
mainActivity.setSupportActionBar(toolbar)
mainActivity.setBottomBarVisibility(View.GONE)
toolbar.title = null
image.transitionName = getString(R.string.transition_album_art)
postponeEnterTransition()
playerActivity?.addMusicServiceEventListener(detailsViewModel)
detailsViewModel.getAlbum().observe(viewLifecycleOwner, Observer {
startPostponedEnterTransition()
showAlbum(it)
startPostponedEnterTransition()
})
detailsViewModel.getArtist().observe(viewLifecycleOwner, Observer {
loadArtistImage(it)

View file

@ -5,6 +5,7 @@ import android.view.View
import androidx.core.os.bundleOf
import androidx.lifecycle.Observer
import androidx.navigation.findNavController
import androidx.navigation.fragment.FragmentNavigatorExtras
import androidx.recyclerview.widget.GridLayoutManager
import code.name.monkey.retromusic.EXTRA_ALBUM_ID
import code.name.monkey.retromusic.R
@ -19,13 +20,12 @@ class AlbumsFragment :
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
libraryViewModel.albumsLiveData
.observe(viewLifecycleOwner, Observer { albums ->
if (albums.isNotEmpty())
adapter?.swapDataSet(albums)
else
adapter?.swapDataSet(listOf())
})
libraryViewModel.albumsLiveData.observe(viewLifecycleOwner, Observer {
if (it.isNotEmpty())
adapter?.swapDataSet(it)
else
adapter?.swapDataSet(listOf())
})
}
override val emptyMessage: Int
@ -98,7 +98,11 @@ class AlbumsFragment :
val controller = requireActivity().findNavController(R.id.fragment_container)
controller.navigate(
R.id.albumDetailsFragment,
bundleOf(EXTRA_ALBUM_ID to albumId)
bundleOf(EXTRA_ALBUM_ID to albumId),
null,
FragmentNavigatorExtras(
view to getString(R.string.transition_album_art)
)
)
}
}

View file

@ -56,17 +56,19 @@ class ArtistDetailsFragment : AbsMainActivityFragment(R.layout.fragment_artist_d
private var lang: String? = null
private var biography: Spanned? = null
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
setHasOptionsMenu(true)
mainActivity.setSupportActionBar(toolbar)
mainActivity.setBottomBarVisibility(View.GONE)
mainActivity.hideBottomBarVisibility(false)
toolbar.title = null
setupRecyclerView()
postponeEnterTransition()
detailsViewModel.getArtist().observe(viewLifecycleOwner, Observer {
startPostponedEnterTransition()
showArtist(it)
startPostponedEnterTransition()
})
detailsViewModel.getArtistInfo().observe(viewLifecycleOwner, Observer {
artistInfo(it)
@ -129,7 +131,7 @@ class ArtistDetailsFragment : AbsMainActivityFragment(R.layout.fragment_artist_d
)
songTitle.text = songText
albumTitle.text = albumText
songAdapter.swapDataSet(artist.songs)
songAdapter.swapDataSet(artist.songs.sortedBy { it.trackNumber })
artist.albums?.let { albumAdapter.swapDataSet(it) }
}
@ -175,6 +177,7 @@ class ArtistDetailsFragment : AbsMainActivityFragment(R.layout.fragment_artist_d
.generatePalette(requireContext()).build()
.dontAnimate().into(object : RetroMusicColoredTarget(image) {
override fun onColorReady(colors: MediaNotificationProcessor) {
startPostponedEnterTransition()
setColors(colors)
}
})

View file

@ -2,6 +2,7 @@ package code.name.monkey.retromusic.fragments.artists
import android.os.Bundle
import android.view.View
import android.widget.ImageView
import androidx.core.os.bundleOf
import androidx.lifecycle.Observer
import androidx.recyclerview.widget.GridLayoutManager
@ -25,14 +26,12 @@ class ArtistsFragment :
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
libraryViewModel.artistsLiveData
.observe(viewLifecycleOwner, Observer { artists ->
if (artists.isNotEmpty()) {
adapter?.swapDataSet(artists)
} else {
adapter?.swapDataSet(listOf())
}
})
libraryViewModel.artistsLiveData.observe(viewLifecycleOwner, Observer {
if (it.isNotEmpty())
adapter?.swapDataSet(it)
else
adapter?.swapDataSet(listOf())
})
}
override val emptyMessage: Int
@ -101,12 +100,12 @@ class ArtistsFragment :
}
}
override fun onArtist(artistId: Int) {
override fun onArtist(artistId: Int, imageView: ImageView) {
val controller = findActivityNavController(R.id.fragment_container)
controller.navigate(R.id.artistDetailsFragment, bundleOf(EXTRA_ARTIST_ID to artistId))
}
}
interface ArtistClickListener {
fun onArtist(artistId: Int)
fun onArtist(artistId: Int, imageView: ImageView)
}

View file

@ -18,12 +18,13 @@ import me.zhanghai.android.fastscroll.FastScroller
import me.zhanghai.android.fastscroll.FastScrollerBuilder
import org.koin.androidx.viewmodel.ext.android.sharedViewModel
abstract class AbsRecyclerViewFragment<A : RecyclerView.Adapter<*>, LM : RecyclerView.LayoutManager> :
AbsMusicServiceFragment(R.layout.fragment_main_activity_recycler_view),
AppBarLayout.OnOffsetChangedListener {
val libraryViewModel: LibraryViewModel by sharedViewModel()
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
setHasOptionsMenu(true)
@ -41,15 +42,17 @@ abstract class AbsRecyclerViewFragment<A : RecyclerView.Adapter<*>, LM : Recycle
}
private fun setUpRecyclerView() {
recyclerView.layoutManager = layoutManager
recyclerView.adapter = adapter
val fastScroller = create(recyclerView)
recyclerView.setOnApplyWindowInsetsListener(
ScrollingViewOnApplyWindowInsetsListener(
recyclerView,
fastScroller
recyclerView.apply {
layoutManager = this@AbsRecyclerViewFragment.layoutManager
adapter = this@AbsRecyclerViewFragment.adapter
val fastScroller = create(this)
setOnApplyWindowInsetsListener(
ScrollingViewOnApplyWindowInsetsListener(
recyclerView,
fastScroller
)
)
)
}
checkForPadding()
}

View file

@ -35,7 +35,7 @@ class GenreDetailsFragment : AbsMainActivityFragment(R.layout.fragment_playlist_
setHasOptionsMenu(true)
mainActivity.addMusicServiceEventListener(detailsViewModel)
mainActivity.setSupportActionBar(toolbar)
mainActivity.setBottomBarVisibility(View.GONE)
mainActivity.hideBottomBarVisibility(false)
setupRecyclerView()
detailsViewModel.getSongs().observe(viewLifecycleOwner, androidx.lifecycle.Observer {

View file

@ -32,14 +32,12 @@ class GenresFragment : AbsRecyclerViewFragment<GenreAdapter, LinearLayoutManager
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
libraryViewModel.genresLiveData
.observe(viewLifecycleOwner, Observer { genres ->
if (genres.isNotEmpty()) {
adapter?.swapDataSet(genres)
} else {
adapter?.swapDataSet(listOf())
}
})
libraryViewModel.genresLiveData.observe(viewLifecycleOwner, Observer {
if (it.isNotEmpty())
adapter?.swapDataSet(it)
else
adapter?.swapDataSet(listOf())
})
}

View file

@ -25,6 +25,7 @@ import androidx.recyclerview.widget.LinearLayoutManager
import code.name.monkey.retromusic.EXTRA_PLAYLIST
import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.adapter.HomeAdapter
import code.name.monkey.retromusic.extensions.findActivityNavController
import code.name.monkey.retromusic.fragments.LibraryViewModel
import code.name.monkey.retromusic.fragments.base.AbsMainActivityFragment
import code.name.monkey.retromusic.glide.ProfileBannerGlideRequest
@ -57,9 +58,7 @@ class HomeFragment :
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
setStatusBarColorAuto(view)
bannerImage?.setOnClickListener {
val options = ActivityOptions.makeSceneTransitionAnimation(
mainActivity,
@ -70,14 +69,14 @@ class HomeFragment :
}
lastAdded.setOnClickListener {
requireActivity().findNavController(R.id.fragment_container).navigate(
findActivityNavController(R.id.fragment_container).navigate(
R.id.playlistDetailsFragment,
bundleOf(EXTRA_PLAYLIST to LastAddedPlaylist(requireActivity()))
)
}
topPlayed.setOnClickListener {
requireActivity().findNavController(R.id.fragment_container).navigate(
findActivityNavController(R.id.fragment_container).navigate(
R.id.playlistDetailsFragment,
bundleOf(EXTRA_PLAYLIST to MyTopTracksPlaylist(requireActivity()))
)
@ -110,9 +109,8 @@ class HomeFragment :
adapter = homeAdapter
}
libraryViewModel.homeLiveData
.observe(viewLifecycleOwner, Observer { sections ->
homeAdapter.swapData(sections)
libraryViewModel.homeLiveData.observe(viewLifecycleOwner, Observer {
homeAdapter.swapData(it)
})
loadProfile()

View file

@ -4,7 +4,6 @@ import android.os.Bundle
import android.view.Menu
import android.view.MenuInflater
import android.view.MenuItem
import android.view.View
import androidx.navigation.fragment.findNavController
import code.name.monkey.appthemehelper.common.ATHToolbarActivity.getToolbarBackgroundColor
import code.name.monkey.appthemehelper.util.ToolbarContentTintHelper
@ -17,11 +16,21 @@ import com.google.android.material.appbar.AppBarLayout
import kotlinx.android.synthetic.main.fragment_library.*
class LibraryFragment : AbsMainActivityFragment(R.layout.fragment_library) {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
override fun onActivityCreated(savedInstanceState: Bundle?) {
super.onActivityCreated(savedInstanceState)
setHasOptionsMenu(true)
mainActivity.setBottomBarVisibility(View.VISIBLE)
mainActivity.hideBottomBarVisibility(true)
mainActivity.setSupportActionBar(toolbar)
mainActivity.supportActionBar?.title = null
toolbar.setNavigationOnClickListener {
findNavController().navigate(
R.id.searchFragment,
null,
navOptions
)
}
setupNavigationController()
}
@ -67,13 +76,8 @@ class LibraryFragment : AbsMainActivityFragment(R.layout.fragment_library) {
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
R.id.action_search -> findNavController().navigate(
R.id.searchFragment,
null,
navOptions
)
R.id.action_settings -> findNavController().navigate(
R.id.settingsFragment,
R.id.settingsActivity,
null,
navOptions
)

View file

@ -43,7 +43,7 @@ class PlaylistDetailsFragment : AbsMainActivityFragment(R.layout.fragment_playli
setHasOptionsMenu(true)
mainActivity.addMusicServiceEventListener(viewModel)
mainActivity.setSupportActionBar(toolbar)
mainActivity.setBottomBarVisibility(View.GONE)
mainActivity.hideBottomBarVisibility(false)
playlist = arguments.extraPlaylist

View file

@ -19,12 +19,11 @@ class PlaylistsFragment :
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
libraryViewModel.playlisitsLiveData.observe(viewLifecycleOwner, Observer { playlists ->
if (playlists.isNotEmpty()) {
adapter?.swapDataSet(playlists)
} else {
libraryViewModel.playlisitsLiveData.observe(viewLifecycleOwner, Observer {
if (it.isNotEmpty())
adapter?.swapDataSet(it)
else
adapter?.swapDataSet(listOf())
}
})
}

View file

@ -39,7 +39,7 @@ class SearchFragment : AbsMainActivityFragment(R.layout.fragment_search), TextWa
super.onViewCreated(view, savedInstanceState)
mainActivity.setSupportActionBar(toolbar)
mainActivity.hideBottomNavigation()
mainActivity.setBottomBarVisibility(View.GONE)
mainActivity.hideBottomBarVisibility(false)
setupRecyclerView()
setupSearchView()

View file

@ -1,23 +0,0 @@
package code.name.monkey.retromusic.fragments.settings
import android.os.Bundle
import android.view.View
import androidx.navigation.NavController
import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.extensions.findNavController
import code.name.monkey.retromusic.fragments.base.AbsMainActivityFragment
import kotlinx.android.synthetic.main.fragment_settings.*
class SettingsFragment : AbsMainActivityFragment(R.layout.fragment_settings) {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
mainActivity.setSupportActionBar(toolbar)
mainActivity.hideBottomNavigation()
mainActivity.setBottomBarVisibility(View.GONE)
val navController: NavController = findNavController(R.id.contentFrame)
navController.addOnDestinationChangedListener { _, _, _ ->
toolbar.title = navController.currentDestination?.label
}
}
}

View file

@ -23,11 +23,10 @@ class SongsFragment :
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
libraryViewModel.songsLiveData.observe(viewLifecycleOwner, Observer {
if (it.isNotEmpty()) {
if (it.isNotEmpty())
adapter?.swapDataSet(it)
} else {
else
adapter?.swapDataSet(listOf())
}
})
}