Code refactor
This commit is contained in:
parent
332c2dc69b
commit
8eb7859f30
6 changed files with 104 additions and 74 deletions
|
@ -55,12 +55,13 @@ private val roomModule = module {
|
||||||
factory {
|
factory {
|
||||||
get<RetroDatabase>().playCountDao()
|
get<RetroDatabase>().playCountDao()
|
||||||
}
|
}
|
||||||
|
|
||||||
factory {
|
factory {
|
||||||
get<RetroDatabase>().historyDao()
|
get<RetroDatabase>().historyDao()
|
||||||
}
|
}
|
||||||
|
|
||||||
single {
|
single {
|
||||||
RealRoomRepository(get(), get(), get())
|
RealRoomRepository(get(), get(), get(), get())
|
||||||
} bind RoomRepository::class
|
} bind RoomRepository::class
|
||||||
}
|
}
|
||||||
private val mainModule = module {
|
private val mainModule = module {
|
||||||
|
|
|
@ -16,7 +16,7 @@ import java.util.*
|
||||||
private const val BASE_QUERY_ARTIST = "search/artist"
|
private const val BASE_QUERY_ARTIST = "search/artist"
|
||||||
private const val BASE_URL = "https://api.deezer.com/"
|
private const val BASE_URL = "https://api.deezer.com/"
|
||||||
|
|
||||||
interface DeezerApiService {
|
interface DeezerService {
|
||||||
|
|
||||||
@GET("$BASE_QUERY_ARTIST&limit=1")
|
@GET("$BASE_QUERY_ARTIST&limit=1")
|
||||||
fun getArtistImage(
|
fun getArtistImage(
|
||||||
|
@ -26,7 +26,7 @@ interface DeezerApiService {
|
||||||
companion object {
|
companion object {
|
||||||
operator fun invoke(
|
operator fun invoke(
|
||||||
client: okhttp3.Call.Factory
|
client: okhttp3.Call.Factory
|
||||||
): DeezerApiService {
|
): DeezerService {
|
||||||
return Retrofit.Builder()
|
return Retrofit.Builder()
|
||||||
.baseUrl(BASE_URL)
|
.baseUrl(BASE_URL)
|
||||||
.callFactory(client)
|
.callFactory(client)
|
|
@ -104,7 +104,7 @@ class DetailListFragment : AbsMainActivityFragment(R.layout.fragment_playlist_de
|
||||||
adapter = songAdapter
|
adapter = songAdapter
|
||||||
layoutManager = linearLayoutManager()
|
layoutManager = linearLayoutManager()
|
||||||
}
|
}
|
||||||
repository.historySong().observe(viewLifecycleOwner, Observer {
|
repository.observableHistorySongs().observe(viewLifecycleOwner, Observer {
|
||||||
val songs = it.map { historyEntity -> historyEntity.toSong() }
|
val songs = it.map { historyEntity -> historyEntity.toSong() }
|
||||||
songAdapter.swapDataSet(songs)
|
songAdapter.swapDataSet(songs)
|
||||||
})
|
})
|
||||||
|
|
|
@ -16,7 +16,7 @@ package code.name.monkey.retromusic.glide.artistimage
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import code.name.monkey.retromusic.deezer.Data
|
import code.name.monkey.retromusic.deezer.Data
|
||||||
import code.name.monkey.retromusic.deezer.DeezerApiService
|
import code.name.monkey.retromusic.deezer.DeezerService
|
||||||
import code.name.monkey.retromusic.util.MusicUtil
|
import code.name.monkey.retromusic.util.MusicUtil
|
||||||
import code.name.monkey.retromusic.util.PreferenceUtil
|
import code.name.monkey.retromusic.util.PreferenceUtil
|
||||||
import com.bumptech.glide.Priority
|
import com.bumptech.glide.Priority
|
||||||
|
@ -38,7 +38,7 @@ class ArtistImage(val artistName: String)
|
||||||
|
|
||||||
class ArtistImageFetcher(
|
class ArtistImageFetcher(
|
||||||
private val context: Context,
|
private val context: Context,
|
||||||
private val deezerApiService: DeezerApiService,
|
private val deezerService: DeezerService,
|
||||||
val model: ArtistImage,
|
val model: ArtistImage,
|
||||||
val urlLoader: ModelLoader<GlideUrl, InputStream>,
|
val urlLoader: ModelLoader<GlideUrl, InputStream>,
|
||||||
val width: Int,
|
val width: Int,
|
||||||
|
@ -66,7 +66,7 @@ class ArtistImageFetcher(
|
||||||
PreferenceUtil.isAllowedToDownloadMetadata()
|
PreferenceUtil.isAllowedToDownloadMetadata()
|
||||||
) {
|
) {
|
||||||
val artists = model.artistName.split(",")
|
val artists = model.artistName.split(",")
|
||||||
val response = deezerApiService.getArtistImage(artists[0]).execute()
|
val response = deezerService.getArtistImage(artists[0]).execute()
|
||||||
|
|
||||||
if (!response.isSuccessful) {
|
if (!response.isSuccessful) {
|
||||||
throw IOException("Request failed with code: " + response.code())
|
throw IOException("Request failed with code: " + response.code())
|
||||||
|
@ -106,7 +106,7 @@ class ArtistImageFetcher(
|
||||||
|
|
||||||
class ArtistImageLoader(
|
class ArtistImageLoader(
|
||||||
val context: Context,
|
val context: Context,
|
||||||
private val deezerApiService: DeezerApiService,
|
private val deezerService: DeezerService,
|
||||||
private val urlLoader: ModelLoader<GlideUrl, InputStream>
|
private val urlLoader: ModelLoader<GlideUrl, InputStream>
|
||||||
) : StreamModelLoader<ArtistImage> {
|
) : StreamModelLoader<ArtistImage> {
|
||||||
|
|
||||||
|
@ -115,7 +115,7 @@ class ArtistImageLoader(
|
||||||
width: Int,
|
width: Int,
|
||||||
height: Int
|
height: Int
|
||||||
): DataFetcher<InputStream> {
|
): DataFetcher<InputStream> {
|
||||||
return ArtistImageFetcher(context, deezerApiService, model, urlLoader, width, height)
|
return ArtistImageFetcher(context, deezerService, model, urlLoader, width, height)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -123,7 +123,7 @@ class Factory(
|
||||||
val context: Context
|
val context: Context
|
||||||
) : ModelLoaderFactory<ArtistImage, InputStream> {
|
) : ModelLoaderFactory<ArtistImage, InputStream> {
|
||||||
|
|
||||||
private var deezerApiService: DeezerApiService
|
private var deezerService: DeezerService
|
||||||
private var okHttpFactory: OkHttpUrlLoader.Factory
|
private var okHttpFactory: OkHttpUrlLoader.Factory
|
||||||
|
|
||||||
init {
|
init {
|
||||||
|
@ -134,8 +134,8 @@ class Factory(
|
||||||
.writeTimeout(TIMEOUT, TimeUnit.MILLISECONDS)
|
.writeTimeout(TIMEOUT, TimeUnit.MILLISECONDS)
|
||||||
.build()
|
.build()
|
||||||
)
|
)
|
||||||
deezerApiService = DeezerApiService.invoke(
|
deezerService = DeezerService.invoke(
|
||||||
DeezerApiService.createDefaultOkHttpClient(context)
|
DeezerService.createDefaultOkHttpClient(context)
|
||||||
.connectTimeout(TIMEOUT, TimeUnit.MILLISECONDS)
|
.connectTimeout(TIMEOUT, TimeUnit.MILLISECONDS)
|
||||||
.readTimeout(TIMEOUT, TimeUnit.MILLISECONDS)
|
.readTimeout(TIMEOUT, TimeUnit.MILLISECONDS)
|
||||||
.writeTimeout(TIMEOUT, TimeUnit.MILLISECONDS)
|
.writeTimeout(TIMEOUT, TimeUnit.MILLISECONDS)
|
||||||
|
@ -156,7 +156,7 @@ class Factory(
|
||||||
): ModelLoader<ArtistImage, InputStream> {
|
): ModelLoader<ArtistImage, InputStream> {
|
||||||
return ArtistImageLoader(
|
return ArtistImageLoader(
|
||||||
context!!,
|
context!!,
|
||||||
deezerApiService,
|
deezerService,
|
||||||
okHttpFactory.build(context, factories)
|
okHttpFactory.build(context, factories)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,14 @@
|
||||||
package code.name.monkey.retromusic.network
|
package code.name.monkey.retromusic.network
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
import code.name.monkey.retromusic.App
|
import code.name.monkey.retromusic.App
|
||||||
import code.name.monkey.retromusic.Constants.AUDIO_SCROBBLER_URL
|
import code.name.monkey.retromusic.BuildConfig
|
||||||
|
import code.name.monkey.retromusic.deezer.DeezerService
|
||||||
import com.google.gson.Gson
|
import com.google.gson.Gson
|
||||||
import okhttp3.Cache
|
import okhttp3.Cache
|
||||||
import okhttp3.ConnectionPool
|
|
||||||
import okhttp3.Interceptor
|
import okhttp3.Interceptor
|
||||||
import okhttp3.OkHttpClient
|
import okhttp3.OkHttpClient
|
||||||
|
import okhttp3.logging.HttpLoggingInterceptor
|
||||||
import org.koin.dsl.module
|
import org.koin.dsl.module
|
||||||
import retrofit2.Retrofit
|
import retrofit2.Retrofit
|
||||||
import retrofit2.converter.gson.GsonConverterFactory
|
import retrofit2.converter.gson.GsonConverterFactory
|
||||||
|
@ -16,50 +18,22 @@ import java.util.concurrent.TimeUnit
|
||||||
private const val TIMEOUT: Long = 700
|
private const val TIMEOUT: Long = 700
|
||||||
|
|
||||||
val networkModule = module {
|
val networkModule = module {
|
||||||
factory {
|
|
||||||
provideHttpClient(get(), get())
|
|
||||||
}
|
|
||||||
factory {
|
|
||||||
provideCacheControlInterceptor()
|
|
||||||
}
|
|
||||||
factory {
|
factory {
|
||||||
provideDefaultCache()
|
provideDefaultCache()
|
||||||
}
|
}
|
||||||
factory {
|
factory {
|
||||||
provideLastFmService(get())
|
provideOkHttp(get(), get())
|
||||||
}
|
}
|
||||||
single {
|
single {
|
||||||
providerRetrofit(get())
|
provideLastFmRetrofit(get())
|
||||||
|
}
|
||||||
|
single {
|
||||||
|
provideDeezerRest(get())
|
||||||
|
}
|
||||||
|
single {
|
||||||
|
provideLastFmRest(get())
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
fun provideLastFmService(retrofit: Retrofit): LastFMService =
|
|
||||||
retrofit.create(LastFMService::class.java)
|
|
||||||
|
|
||||||
fun providerRetrofit(okHttpClient: OkHttpClient.Builder): Retrofit = Retrofit.Builder()
|
|
||||||
.baseUrl(AUDIO_SCROBBLER_URL)
|
|
||||||
.callFactory(okHttpClient.build())
|
|
||||||
.addConverterFactory(GsonConverterFactory.create(Gson()))
|
|
||||||
.build()
|
|
||||||
|
|
||||||
fun provideHttpClient(
|
|
||||||
cache: Cache,
|
|
||||||
interceptor: Interceptor
|
|
||||||
): OkHttpClient.Builder = OkHttpClient.Builder()
|
|
||||||
.connectionPool(ConnectionPool(0, 1, TimeUnit.NANOSECONDS))
|
|
||||||
.retryOnConnectionFailure(true)
|
|
||||||
.connectTimeout(TIMEOUT, TimeUnit.MINUTES)
|
|
||||||
.writeTimeout(TIMEOUT, TimeUnit.MINUTES)
|
|
||||||
.readTimeout(TIMEOUT, TimeUnit.MINUTES)
|
|
||||||
.cache(cache)
|
|
||||||
.addInterceptor(interceptor)
|
|
||||||
|
|
||||||
|
|
||||||
fun provideCacheControlInterceptor(): Interceptor = Interceptor { chain: Interceptor.Chain ->
|
|
||||||
val modifiedRequest = chain.request().newBuilder()
|
|
||||||
.addHeader("Cache-Control", "max-age=31536000, max-stale=31536000")
|
|
||||||
.build()
|
|
||||||
chain.proceed(modifiedRequest)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun provideDefaultCache(): Cache? {
|
fun provideDefaultCache(): Cache? {
|
||||||
|
@ -69,3 +43,55 @@ fun provideDefaultCache(): Cache? {
|
||||||
}
|
}
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun logInterceptor(): Interceptor {
|
||||||
|
val loggingInterceptor = HttpLoggingInterceptor()
|
||||||
|
if (BuildConfig.DEBUG) {
|
||||||
|
loggingInterceptor.level = HttpLoggingInterceptor.Level.BODY
|
||||||
|
} else {
|
||||||
|
// disable retrofit log on release
|
||||||
|
loggingInterceptor.level = HttpLoggingInterceptor.Level.NONE
|
||||||
|
}
|
||||||
|
return loggingInterceptor
|
||||||
|
}
|
||||||
|
|
||||||
|
fun headerInterceptor(context: Context): Interceptor {
|
||||||
|
return Interceptor {
|
||||||
|
val original = it.request()
|
||||||
|
val request = original.newBuilder()
|
||||||
|
.header("User-Agent", context.packageName)
|
||||||
|
.addHeader("Content-Type", "application/json; charset=utf-8")
|
||||||
|
.method(original.method(), original.body())
|
||||||
|
.build()
|
||||||
|
it.proceed(request)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun provideOkHttp(context: Context, cache: Cache): OkHttpClient {
|
||||||
|
return OkHttpClient.Builder()
|
||||||
|
.addNetworkInterceptor(logInterceptor())
|
||||||
|
.addInterceptor(headerInterceptor(context))
|
||||||
|
.connectTimeout(1, TimeUnit.SECONDS)
|
||||||
|
.readTimeout(1, TimeUnit.SECONDS)
|
||||||
|
.cache(cache)
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun provideLastFmRetrofit(client: OkHttpClient): Retrofit {
|
||||||
|
return Retrofit.Builder()
|
||||||
|
.baseUrl("https://ws.audioscrobbler.com/2.0/")
|
||||||
|
.addConverterFactory(GsonConverterFactory.create(Gson()))
|
||||||
|
.callFactory { request -> client.newCall(request) }
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun provideLastFmRest(retrofit: Retrofit): LastFMService {
|
||||||
|
return retrofit.create(LastFMService::class.java)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun provideDeezerRest(retrofit: Retrofit): DeezerService {
|
||||||
|
val newBuilder = retrofit.newBuilder()
|
||||||
|
.baseUrl("https://api.deezer.com/")
|
||||||
|
.build()
|
||||||
|
return newBuilder.create(DeezerService::class.java)
|
||||||
|
}
|
|
@ -22,6 +22,7 @@ import code.name.monkey.retromusic.model.*
|
||||||
import code.name.monkey.retromusic.model.smartplaylist.NotPlayedPlaylist
|
import code.name.monkey.retromusic.model.smartplaylist.NotPlayedPlaylist
|
||||||
import code.name.monkey.retromusic.network.LastFMService
|
import code.name.monkey.retromusic.network.LastFMService
|
||||||
import code.name.monkey.retromusic.network.Result
|
import code.name.monkey.retromusic.network.Result
|
||||||
|
import code.name.monkey.retromusic.network.Result.*
|
||||||
import code.name.monkey.retromusic.network.model.LastFmAlbum
|
import code.name.monkey.retromusic.network.model.LastFmAlbum
|
||||||
import code.name.monkey.retromusic.network.model.LastFmArtist
|
import code.name.monkey.retromusic.network.model.LastFmArtist
|
||||||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||||
|
@ -153,9 +154,10 @@ class RealRepository(
|
||||||
cache: String?
|
cache: String?
|
||||||
): Result<LastFmArtist> {
|
): Result<LastFmArtist> {
|
||||||
return try {
|
return try {
|
||||||
Result.Success(lastFMService.artistInfo(name, lang, cache))
|
Success(lastFMService.artistInfo(name, lang, cache))
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Result.Error
|
println(e)
|
||||||
|
Error
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -165,15 +167,16 @@ class RealRepository(
|
||||||
): Result<LastFmAlbum> {
|
): Result<LastFmAlbum> {
|
||||||
return try {
|
return try {
|
||||||
val lastFmAlbum = lastFMService.albumInfo(artist, album)
|
val lastFmAlbum = lastFMService.albumInfo(artist, album)
|
||||||
Result.Success(lastFmAlbum)
|
Success(lastFmAlbum)
|
||||||
} catch (e: Exception) {
|
} catch (e: Exception) {
|
||||||
Result.Error
|
println(e)
|
||||||
|
Error
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ExperimentalCoroutinesApi
|
@ExperimentalCoroutinesApi
|
||||||
override suspend fun homeSectionsFlow(): Flow<Result<List<Home>>> {
|
override suspend fun homeSectionsFlow(): Flow<Result<List<Home>>> {
|
||||||
val homes = MutableStateFlow<Result<List<Home>>>(value = Result.Loading)
|
val homes = MutableStateFlow<Result<List<Home>>>(value = Loading)
|
||||||
val homeSections = mutableListOf<Home>()
|
val homeSections = mutableListOf<Home>()
|
||||||
val sections = listOf(
|
val sections = listOf(
|
||||||
topArtistsHome(),
|
topArtistsHome(),
|
||||||
|
@ -191,9 +194,9 @@ class RealRepository(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (homeSections.isEmpty()) {
|
if (homeSections.isEmpty()) {
|
||||||
homes.value = Result.Error
|
homes.value = Error
|
||||||
} else {
|
} else {
|
||||||
homes.value = Result.Success(homeSections)
|
homes.value = Success(homeSections)
|
||||||
}
|
}
|
||||||
return homes
|
return homes
|
||||||
}
|
}
|
||||||
|
@ -350,52 +353,52 @@ class RealRepository(
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun songsFlow(): Flow<Result<List<Song>>> = flow {
|
override fun songsFlow(): Flow<Result<List<Song>>> = flow {
|
||||||
emit(Result.Loading)
|
emit(Loading)
|
||||||
val data = songRepository.songs()
|
val data = songRepository.songs()
|
||||||
if (data.isEmpty()) {
|
if (data.isEmpty()) {
|
||||||
emit(Result.Error)
|
emit(Error)
|
||||||
} else {
|
} else {
|
||||||
emit(Result.Success(data))
|
emit(Success(data))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun albumsFlow(): Flow<Result<List<Album>>> = flow {
|
override fun albumsFlow(): Flow<Result<List<Album>>> = flow {
|
||||||
emit(Result.Loading)
|
emit(Loading)
|
||||||
val data = albumRepository.albums()
|
val data = albumRepository.albums()
|
||||||
if (data.isEmpty()) {
|
if (data.isEmpty()) {
|
||||||
emit(Result.Error)
|
emit(Error)
|
||||||
} else {
|
} else {
|
||||||
emit(Result.Success(data))
|
emit(Success(data))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun artistsFlow(): Flow<Result<List<Artist>>> = flow {
|
override fun artistsFlow(): Flow<Result<List<Artist>>> = flow {
|
||||||
emit(Result.Loading)
|
emit(Loading)
|
||||||
val data = artistRepository.artists()
|
val data = artistRepository.artists()
|
||||||
if (data.isEmpty()) {
|
if (data.isEmpty()) {
|
||||||
emit(Result.Error)
|
emit(Error)
|
||||||
} else {
|
} else {
|
||||||
emit(Result.Success(data))
|
emit(Success(data))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun playlistsFlow(): Flow<Result<List<Playlist>>> = flow {
|
override fun playlistsFlow(): Flow<Result<List<Playlist>>> = flow {
|
||||||
emit(Result.Loading)
|
emit(Loading)
|
||||||
val data = playlistRepository.playlists()
|
val data = playlistRepository.playlists()
|
||||||
if (data.isEmpty()) {
|
if (data.isEmpty()) {
|
||||||
emit(Result.Error)
|
emit(Error)
|
||||||
} else {
|
} else {
|
||||||
emit(Result.Success(data))
|
emit(Success(data))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun genresFlow(): Flow<Result<List<Genre>>> = flow {
|
override fun genresFlow(): Flow<Result<List<Genre>>> = flow {
|
||||||
emit(Result.Loading)
|
emit(Loading)
|
||||||
val data = genreRepository.genres()
|
val data = genreRepository.genres()
|
||||||
if (data.isEmpty()) {
|
if (data.isEmpty()) {
|
||||||
emit(Result.Error)
|
emit(Error)
|
||||||
} else {
|
} else {
|
||||||
emit(Result.Success(data))
|
emit(Success(data))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in a new issue