Refactor code
This commit is contained in:
parent
016c7f6218
commit
67f4b4ecf2
4 changed files with 125 additions and 108 deletions
|
@ -11,7 +11,7 @@ import retrofit2.create
|
||||||
import retrofit2.http.GET
|
import retrofit2.http.GET
|
||||||
import retrofit2.http.Query
|
import retrofit2.http.Query
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.util.*
|
import java.util.Locale
|
||||||
|
|
||||||
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/"
|
||||||
|
@ -20,30 +20,30 @@ interface DeezerApiService {
|
||||||
|
|
||||||
@GET("$BASE_QUERY_ARTIST&limit=1")
|
@GET("$BASE_QUERY_ARTIST&limit=1")
|
||||||
fun getArtistImage(
|
fun getArtistImage(
|
||||||
@Query("q") artistName: String
|
@Query("q") artistName: String
|
||||||
): Call<DeezerResponse>
|
): Call<DeezerResponse>
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
operator fun invoke(
|
operator fun invoke(
|
||||||
client: okhttp3.Call.Factory
|
client: okhttp3.Call.Factory
|
||||||
): DeezerApiService {
|
): DeezerApiService {
|
||||||
return Retrofit.Builder()
|
return Retrofit.Builder()
|
||||||
.baseUrl(BASE_URL)
|
.baseUrl(BASE_URL)
|
||||||
.callFactory(client)
|
.callFactory(client)
|
||||||
.addConverterFactory(GsonConverterFactory.create())
|
.addConverterFactory(GsonConverterFactory.create())
|
||||||
.build()
|
.build()
|
||||||
.create()
|
.create()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun createDefaultOkHttpClient(
|
fun createDefaultOkHttpClient(
|
||||||
context: Context
|
context: Context
|
||||||
): OkHttpClient.Builder =
|
): OkHttpClient.Builder =
|
||||||
OkHttpClient.Builder()
|
OkHttpClient.Builder()
|
||||||
.cache(createDefaultCache(context))
|
.cache(createDefaultCache(context))
|
||||||
.addInterceptor(createCacheControlInterceptor())
|
.addInterceptor(createCacheControlInterceptor())
|
||||||
|
|
||||||
private fun createDefaultCache(
|
private fun createDefaultCache(
|
||||||
context: Context
|
context: Context
|
||||||
): Cache? {
|
): Cache? {
|
||||||
val cacheDir = File(context.applicationContext.cacheDir.absolutePath, "/okhttp-deezer/")
|
val cacheDir = File(context.applicationContext.cacheDir.absolutePath, "/okhttp-deezer/")
|
||||||
if (cacheDir.mkdir() or cacheDir.isDirectory) {
|
if (cacheDir.mkdir() or cacheDir.isDirectory) {
|
||||||
|
@ -55,12 +55,13 @@ interface DeezerApiService {
|
||||||
private fun createCacheControlInterceptor(): Interceptor {
|
private fun createCacheControlInterceptor(): Interceptor {
|
||||||
return Interceptor { chain ->
|
return Interceptor { chain ->
|
||||||
val modifiedRequest = chain.request().newBuilder()
|
val modifiedRequest = chain.request().newBuilder()
|
||||||
.addHeader("Cache-Control",
|
.addHeader(
|
||||||
String.format(
|
"Cache-Control",
|
||||||
Locale.getDefault(),
|
String.format(
|
||||||
"max-age=31536000, max-stale=31536000"
|
Locale.getDefault(),
|
||||||
)
|
"max-age=31536000, max-stale=31536000"
|
||||||
).build()
|
)
|
||||||
|
).build()
|
||||||
chain.proceed(modifiedRequest)
|
chain.proceed(modifiedRequest)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,29 +3,29 @@ package code.name.monkey.retromusic.deezer
|
||||||
import com.google.gson.annotations.SerializedName
|
import com.google.gson.annotations.SerializedName
|
||||||
|
|
||||||
data class Data(
|
data class Data(
|
||||||
val id: String,
|
val id: String,
|
||||||
val link: String,
|
val link: String,
|
||||||
val name: String,
|
val name: String,
|
||||||
@SerializedName("nb_album")
|
@SerializedName("nb_album")
|
||||||
val nbAlbum: Int,
|
val nbAlbum: Int,
|
||||||
@SerializedName("nb_fan")
|
@SerializedName("nb_fan")
|
||||||
val nbFan: Int,
|
val nbFan: Int,
|
||||||
val picture: String,
|
val picture: String,
|
||||||
@SerializedName("picture_big")
|
@SerializedName("picture_big")
|
||||||
val pictureBig: String,
|
val pictureBig: String,
|
||||||
@SerializedName("picture_medium")
|
@SerializedName("picture_medium")
|
||||||
val pictureMedium: String,
|
val pictureMedium: String,
|
||||||
@SerializedName("picture_small")
|
@SerializedName("picture_small")
|
||||||
val pictureSmall: String,
|
val pictureSmall: String,
|
||||||
@SerializedName("picture_xl")
|
@SerializedName("picture_xl")
|
||||||
val pictureXl: String,
|
val pictureXl: String,
|
||||||
val radio: Boolean,
|
val radio: Boolean,
|
||||||
val tracklist: String,
|
val tracklist: String,
|
||||||
val type: String
|
val type: String
|
||||||
)
|
)
|
||||||
|
|
||||||
data class DeezerResponse(
|
data class DeezerResponse(
|
||||||
val data: List<Data>,
|
val data: List<Data>,
|
||||||
val next: String,
|
val next: String,
|
||||||
val total: Int
|
val total: Int
|
||||||
)
|
)
|
|
@ -16,9 +16,15 @@ package code.name.monkey.retromusic.glide;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
import code.name.monkey.retromusic.App;
|
||||||
|
import code.name.monkey.retromusic.R;
|
||||||
|
import code.name.monkey.retromusic.glide.artistimage.ArtistImage;
|
||||||
|
import code.name.monkey.retromusic.glide.palette.BitmapPaletteTranscoder;
|
||||||
|
import code.name.monkey.retromusic.glide.palette.BitmapPaletteWrapper;
|
||||||
|
import code.name.monkey.retromusic.model.Artist;
|
||||||
|
import code.name.monkey.retromusic.util.ArtistSignatureUtil;
|
||||||
|
import code.name.monkey.retromusic.util.CustomArtistImageUtil;
|
||||||
import com.bumptech.glide.BitmapRequestBuilder;
|
import com.bumptech.glide.BitmapRequestBuilder;
|
||||||
import com.bumptech.glide.DrawableRequestBuilder;
|
import com.bumptech.glide.DrawableRequestBuilder;
|
||||||
import com.bumptech.glide.DrawableTypeRequest;
|
import com.bumptech.glide.DrawableTypeRequest;
|
||||||
|
@ -29,68 +35,32 @@ import com.bumptech.glide.load.engine.DiskCacheStrategy;
|
||||||
import com.bumptech.glide.load.resource.drawable.GlideDrawable;
|
import com.bumptech.glide.load.resource.drawable.GlideDrawable;
|
||||||
import com.bumptech.glide.request.target.Target;
|
import com.bumptech.glide.request.target.Target;
|
||||||
|
|
||||||
import code.name.monkey.retromusic.App;
|
|
||||||
import code.name.monkey.retromusic.R;
|
|
||||||
import code.name.monkey.retromusic.glide.artistimage.ArtistImage;
|
|
||||||
import code.name.monkey.retromusic.glide.palette.BitmapPaletteTranscoder;
|
|
||||||
import code.name.monkey.retromusic.glide.palette.BitmapPaletteWrapper;
|
|
||||||
import code.name.monkey.retromusic.model.Artist;
|
|
||||||
import code.name.monkey.retromusic.util.ArtistSignatureUtil;
|
|
||||||
import code.name.monkey.retromusic.util.CustomArtistImageUtil;
|
|
||||||
|
|
||||||
|
|
||||||
public class ArtistGlideRequest {
|
public class ArtistGlideRequest {
|
||||||
|
|
||||||
public static final int DEFAULT_ANIMATION = android.R.anim.fade_in;
|
|
||||||
private static final DiskCacheStrategy DEFAULT_DISK_CACHE_STRATEGY = DiskCacheStrategy.SOURCE;
|
|
||||||
private static final int DEFAULT_ERROR_IMAGE = R.drawable.default_artist_art;
|
|
||||||
|
|
||||||
public static DrawableTypeRequest createBaseRequest(RequestManager requestManager, Artist artist, boolean noCustomImage, boolean forceDownload) {
|
|
||||||
boolean hasCustomImage = CustomArtistImageUtil.Companion.getInstance(App.Companion.getContext()).hasCustomArtistImage(artist);
|
|
||||||
if (noCustomImage || !hasCustomImage) {
|
|
||||||
return requestManager.load(new ArtistImage(artist.getName(), forceDownload));
|
|
||||||
} else {
|
|
||||||
return requestManager.load(CustomArtistImageUtil.getFile(artist));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Key createSignature(Artist artist) {
|
|
||||||
return ArtistSignatureUtil.getInstance(App.Companion.getContext()).getArtistSignature(artist.getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class Builder {
|
public static class Builder {
|
||||||
final RequestManager requestManager;
|
|
||||||
final Artist artist;
|
final Artist artist;
|
||||||
boolean noCustomImage;
|
|
||||||
boolean forceDownload;
|
boolean forceDownload;
|
||||||
|
|
||||||
|
boolean noCustomImage;
|
||||||
|
|
||||||
|
final RequestManager requestManager;
|
||||||
|
|
||||||
|
public static Builder from(@NonNull RequestManager requestManager, Artist artist) {
|
||||||
|
return new Builder(requestManager, artist);
|
||||||
|
}
|
||||||
|
|
||||||
private Builder(@NonNull RequestManager requestManager, Artist artist) {
|
private Builder(@NonNull RequestManager requestManager, Artist artist) {
|
||||||
this.requestManager = requestManager;
|
this.requestManager = requestManager;
|
||||||
this.artist = artist;
|
this.artist = artist;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Builder from(@NonNull RequestManager requestManager, Artist artist) {
|
|
||||||
return new Builder(requestManager, artist);
|
|
||||||
}
|
|
||||||
|
|
||||||
public PaletteBuilder generatePalette(Context context) {
|
|
||||||
return new PaletteBuilder(this, context);
|
|
||||||
}
|
|
||||||
|
|
||||||
public BitmapBuilder asBitmap() {
|
public BitmapBuilder asBitmap() {
|
||||||
return new BitmapBuilder(this);
|
return new BitmapBuilder(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Builder noCustomImage(boolean noCustomImage) {
|
|
||||||
this.noCustomImage = noCustomImage;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder forceDownload(boolean forceDownload) {
|
|
||||||
this.forceDownload = forceDownload;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public DrawableRequestBuilder<GlideDrawable> build() {
|
public DrawableRequestBuilder<GlideDrawable> build() {
|
||||||
//noinspection unchecked
|
//noinspection unchecked
|
||||||
return createBaseRequest(requestManager, artist, noCustomImage, forceDownload)
|
return createBaseRequest(requestManager, artist, noCustomImage, forceDownload)
|
||||||
|
@ -101,9 +71,24 @@ public class ArtistGlideRequest {
|
||||||
.override(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL)
|
.override(Target.SIZE_ORIGINAL, Target.SIZE_ORIGINAL)
|
||||||
.signature(createSignature(artist));
|
.signature(createSignature(artist));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Builder forceDownload(boolean forceDownload) {
|
||||||
|
this.forceDownload = forceDownload;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PaletteBuilder generatePalette(Context context) {
|
||||||
|
return new PaletteBuilder(this, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Builder noCustomImage(boolean noCustomImage) {
|
||||||
|
this.noCustomImage = noCustomImage;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class BitmapBuilder {
|
public static class BitmapBuilder {
|
||||||
|
|
||||||
private final Builder builder;
|
private final Builder builder;
|
||||||
|
|
||||||
public BitmapBuilder(Builder builder) {
|
public BitmapBuilder(Builder builder) {
|
||||||
|
@ -112,7 +97,8 @@ public class ArtistGlideRequest {
|
||||||
|
|
||||||
public BitmapRequestBuilder<?, Bitmap> build() {
|
public BitmapRequestBuilder<?, Bitmap> build() {
|
||||||
//noinspection unchecked
|
//noinspection unchecked
|
||||||
return createBaseRequest(builder.requestManager, builder.artist, builder.noCustomImage, builder.forceDownload)
|
return createBaseRequest(builder.requestManager, builder.artist, builder.noCustomImage,
|
||||||
|
builder.forceDownload)
|
||||||
.asBitmap()
|
.asBitmap()
|
||||||
.diskCacheStrategy(DEFAULT_DISK_CACHE_STRATEGY)
|
.diskCacheStrategy(DEFAULT_DISK_CACHE_STRATEGY)
|
||||||
.error(DEFAULT_ERROR_IMAGE)
|
.error(DEFAULT_ERROR_IMAGE)
|
||||||
|
@ -124,7 +110,9 @@ public class ArtistGlideRequest {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class PaletteBuilder {
|
public static class PaletteBuilder {
|
||||||
|
|
||||||
final Context context;
|
final Context context;
|
||||||
|
|
||||||
private final Builder builder;
|
private final Builder builder;
|
||||||
|
|
||||||
public PaletteBuilder(Builder builder, Context context) {
|
public PaletteBuilder(Builder builder, Context context) {
|
||||||
|
@ -134,7 +122,8 @@ public class ArtistGlideRequest {
|
||||||
|
|
||||||
public BitmapRequestBuilder<?, BitmapPaletteWrapper> build() {
|
public BitmapRequestBuilder<?, BitmapPaletteWrapper> build() {
|
||||||
//noinspection unchecked
|
//noinspection unchecked
|
||||||
return createBaseRequest(builder.requestManager, builder.artist, builder.noCustomImage, builder.forceDownload)
|
return createBaseRequest(builder.requestManager, builder.artist, builder.noCustomImage,
|
||||||
|
builder.forceDownload)
|
||||||
.asBitmap()
|
.asBitmap()
|
||||||
.transcode(new BitmapPaletteTranscoder(context), BitmapPaletteWrapper.class)
|
.transcode(new BitmapPaletteTranscoder(context), BitmapPaletteWrapper.class)
|
||||||
.diskCacheStrategy(DEFAULT_DISK_CACHE_STRATEGY)
|
.diskCacheStrategy(DEFAULT_DISK_CACHE_STRATEGY)
|
||||||
|
@ -145,6 +134,30 @@ public class ArtistGlideRequest {
|
||||||
.signature(createSignature(builder.artist));
|
.signature(createSignature(builder.artist));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static final int DEFAULT_ANIMATION = android.R.anim.fade_in;
|
||||||
|
|
||||||
|
private static final DiskCacheStrategy DEFAULT_DISK_CACHE_STRATEGY = DiskCacheStrategy.SOURCE;
|
||||||
|
|
||||||
|
private static final int DEFAULT_ERROR_IMAGE = R.drawable.default_artist_art;
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
public static Key createSignature(@NonNull Artist artist) {
|
||||||
|
return ArtistSignatureUtil.getInstance(App.Companion.getContext()).getArtistSignature(artist.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
@NonNull
|
||||||
|
private static DrawableTypeRequest createBaseRequest(@NonNull RequestManager requestManager,
|
||||||
|
@NonNull Artist artist,
|
||||||
|
boolean noCustomImage, boolean forceDownload) {
|
||||||
|
boolean hasCustomImage = CustomArtistImageUtil.Companion.getInstance(App.Companion.getContext())
|
||||||
|
.hasCustomArtistImage(artist);
|
||||||
|
if (noCustomImage || !hasCustomImage) {
|
||||||
|
return requestManager.load(new ArtistImage(artist.getName()));
|
||||||
|
} else {
|
||||||
|
return requestManager.load(CustomArtistImageUtil.getFile(artist));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -32,16 +32,15 @@ import java.io.IOException
|
||||||
import java.io.InputStream
|
import java.io.InputStream
|
||||||
import java.util.concurrent.TimeUnit
|
import java.util.concurrent.TimeUnit
|
||||||
|
|
||||||
|
class ArtistImage(val artistName: String)
|
||||||
class ArtistImage(val artistName: String, val skipOkHttpCache: Boolean)
|
|
||||||
|
|
||||||
class ArtistImageFetcher(
|
class ArtistImageFetcher(
|
||||||
private val context: Context,
|
private val context: Context,
|
||||||
private val deezerApiService: DeezerApiService,
|
private val deezerApiService: DeezerApiService,
|
||||||
val model: ArtistImage,
|
val model: ArtistImage,
|
||||||
val urlLoader: ModelLoader<GlideUrl, InputStream>,
|
val urlLoader: ModelLoader<GlideUrl, InputStream>,
|
||||||
val width: Int,
|
val width: Int,
|
||||||
val height: Int
|
val height: Int
|
||||||
) : DataFetcher<InputStream> {
|
) : DataFetcher<InputStream> {
|
||||||
|
|
||||||
private var urlFetcher: DataFetcher<InputStream>? = null
|
private var urlFetcher: DataFetcher<InputStream>? = null
|
||||||
|
@ -96,9 +95,9 @@ class ArtistImageFetcher(
|
||||||
}
|
}
|
||||||
|
|
||||||
class ArtistImageLoader(
|
class ArtistImageLoader(
|
||||||
val context: Context,
|
val context: Context,
|
||||||
private val deezerApiService: DeezerApiService,
|
private val deezerApiService: DeezerApiService,
|
||||||
private val urlLoader: ModelLoader<GlideUrl, InputStream>
|
private val urlLoader: ModelLoader<GlideUrl, InputStream>
|
||||||
) : StreamModelLoader<ArtistImage> {
|
) : StreamModelLoader<ArtistImage> {
|
||||||
|
|
||||||
override fun getResourceFetcher(model: ArtistImage, width: Int, height: Int): DataFetcher<InputStream> {
|
override fun getResourceFetcher(model: ArtistImage, width: Int, height: Int): DataFetcher<InputStream> {
|
||||||
|
@ -107,22 +106,27 @@ class ArtistImageLoader(
|
||||||
}
|
}
|
||||||
|
|
||||||
class Factory(
|
class Factory(
|
||||||
val context: Context
|
val context: Context
|
||||||
) : ModelLoaderFactory<ArtistImage, InputStream> {
|
) : ModelLoaderFactory<ArtistImage, InputStream> {
|
||||||
|
|
||||||
private var deezerApiService: DeezerApiService
|
private var deezerApiService: DeezerApiService
|
||||||
private var okHttpFactory: OkHttpUrlLoader.Factory
|
private var okHttpFactory: OkHttpUrlLoader.Factory
|
||||||
|
|
||||||
init {
|
init {
|
||||||
okHttpFactory = OkHttpUrlLoader.Factory(OkHttpClient.Builder()
|
okHttpFactory = OkHttpUrlLoader.Factory(
|
||||||
|
OkHttpClient.Builder()
|
||||||
.connectTimeout(TIMEOUT, TimeUnit.MILLISECONDS)
|
.connectTimeout(TIMEOUT, TimeUnit.MILLISECONDS)
|
||||||
.readTimeout(TIMEOUT, TimeUnit.MILLISECONDS)
|
.readTimeout(TIMEOUT, TimeUnit.MILLISECONDS)
|
||||||
.writeTimeout(TIMEOUT, TimeUnit.MILLISECONDS)
|
.writeTimeout(TIMEOUT, TimeUnit.MILLISECONDS)
|
||||||
.build())
|
.build()
|
||||||
deezerApiService = DeezerApiService.invoke(DeezerApiService.createDefaultOkHttpClient(context)
|
)
|
||||||
|
deezerApiService = DeezerApiService.invoke(
|
||||||
|
DeezerApiService.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)
|
||||||
.build())
|
.build()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun build(context: Context?, factories: GenericLoaderFactory?): ModelLoader<ArtistImage, InputStream> {
|
override fun build(context: Context?, factories: GenericLoaderFactory?): ModelLoader<ArtistImage, InputStream> {
|
||||||
|
@ -137,5 +141,4 @@ class Factory(
|
||||||
// we need these very low values to make sure our artist image loading calls doesn't block the image loading queue
|
// we need these very low values to make sure our artist image loading calls doesn't block the image loading queue
|
||||||
private const val TIMEOUT: Long = 700
|
private const val TIMEOUT: Long = 700
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue