瀏覽代碼

Added ApiManager for executing API calls and refactored FlickrServiceLogic

Ana Sekuloski 3 年之前
父節點
當前提交
3c792fe3be

+ 3 - 3
flickersearchlibrary/src/main/java/com/livelike/flickersearchlibrary/api/FlickrApi.kt

@@ -1,6 +1,6 @@
 package com.livelike.flickersearchlibrary.api
 
-import com.livelike.flickersearchlibrary.api.model.response.SearchResponse
+import com.livelike.flickersearchlibrary.api.model.response.FlickrResponse
 import com.livelike.flickersearchlibrary.api.utils.*
 import retrofit2.Response
 import retrofit2.http.GET
@@ -18,7 +18,7 @@ internal interface FlickrApi {
         @Query(QUERY_API_KEY) apiKey: String = DEFAULT_API_KEY,
         @Query(QUERY_FORMAT) format: String = JSON_FORMAT,
         @Query(QUERY_NO_JSON_CALLBACK) noJsonCallback: Boolean = NO_JSON_CALLBACK,
-    ): Response<SearchResponse>
+    ): Response<FlickrResponse>
 
     @GET(".")
     suspend fun getRecent(
@@ -26,5 +26,5 @@ internal interface FlickrApi {
         @Query(QUERY_API_KEY) apiKey: String = DEFAULT_API_KEY,
         @Query(QUERY_FORMAT) format: String = JSON_FORMAT,
         @Query(QUERY_NO_JSON_CALLBACK) noJsonCallback: Boolean = NO_JSON_CALLBACK,
-    ): Response<SearchResponse>
+    ): Response<FlickrResponse>
 }

+ 11 - 0
flickersearchlibrary/src/main/java/com/livelike/flickersearchlibrary/api/model/response/ApiResponse.kt

@@ -0,0 +1,11 @@
+package com.livelike.flickersearchlibrary.api.model.response
+
+import com.livelike.flickersearchlibrary.api.model.Photo
+
+/**
+ * Represents possible states of API response.
+ */
+internal sealed class ApiResponse {
+    data class Success(val body: List<Photo>) : ApiResponse()
+    data class Error(val message: String) : ApiResponse()
+}

+ 1 - 1
flickersearchlibrary/src/main/java/com/livelike/flickersearchlibrary/api/model/response/SearchResponse.kt → flickersearchlibrary/src/main/java/com/livelike/flickersearchlibrary/api/model/response/FlickrResponse.kt

@@ -3,7 +3,7 @@ package com.livelike.flickersearchlibrary.api.model.response
 import com.livelike.flickersearchlibrary.api.model.PhotosPage
 import com.squareup.moshi.Json
 
-internal data class SearchResponse(
+internal data class FlickrResponse(
     @Json(name = "photos")
     val photosPage: PhotosPage
 )

+ 33 - 0
flickersearchlibrary/src/main/java/com/livelike/flickersearchlibrary/api/utils/ApiManager.kt

@@ -0,0 +1,33 @@
+package com.livelike.flickersearchlibrary.api.utils
+
+import android.util.Log
+import com.livelike.flickersearchlibrary.api.model.response.ApiResponse
+import com.livelike.flickersearchlibrary.api.model.response.FlickrResponse
+import retrofit2.Response
+
+/**
+ * Executes given Flickr API call and handles errors or exceptions.
+ *
+ * @return [ApiResponse] with state and data depending on executed API call.
+ */
+internal suspend fun executeApiCall(apiCall: suspend () -> Response<FlickrResponse>): ApiResponse {
+    return runCatching {
+        val response = apiCall()
+        if (response.isSuccessful) {
+            ApiResponse.Success(response.body()?.photosPage?.photos ?: emptyList())
+        } else {
+            throw Exception(
+                "Flickr API responded with error: ${
+                    response.errorBody().toString()
+                }"
+            )
+        }
+    }.onFailure { exception: Throwable ->
+        Log.d(
+            "FlickrApiManager",
+            "Exception occurred when executing API call: ${exception.message}"
+        )
+    }.getOrElse { exception: Throwable ->
+        ApiResponse.Error(exception.message.orEmpty())
+    }
+}

+ 17 - 43
flickersearchlibrary/src/main/java/com/livelike/flickersearchlibrary/service/logic/FlickrServiceLogic.kt

@@ -1,8 +1,9 @@
 package com.livelike.flickersearchlibrary.service.logic
 
-import android.util.Log
 import com.livelike.flickersearchlibrary.api.FlickrApi
 import com.livelike.flickersearchlibrary.api.model.Photo
+import com.livelike.flickersearchlibrary.api.model.response.ApiResponse
+import com.livelike.flickersearchlibrary.api.utils.executeApiCall
 import com.livelike.flickersearchlibrary.service.FlickrService
 
 /**
@@ -12,53 +13,26 @@ internal class FlickrServiceLogic(private val api: FlickrApi) : FlickrService {
 
     private val cachedPhotos = mutableListOf<Photo>()
 
-    private val LOG_TAG = "FlickrService"
-
     override suspend fun search(searchQuery: String?) =
         searchQuery?.let {
-            updateCachedPhotos(searchQuery)
+            val response = executeApiCall {
+                api.search(searchQuery)
+            }
+            if (response is ApiResponse.Success) {
+                cachedPhotos.clear()
+                cachedPhotos.addAll(response.body)
+            }
+
             cachedPhotos
         } ?: emptyList()
 
     override suspend fun getRecentPhotos(): List<Photo> {
-        return runCatching {
-            val response = api.getRecent()
-            if (response.isSuccessful) {
-                response.body()?.photosPage?.photos ?: emptyList()
-            } else {
-                throw Exception(
-                    "Flickr API responded with error: ${
-                        response.errorBody().toString()
-                    }"
-                )
-            }
-        }.onFailure { exception: Throwable ->
-            Log.d(
-                LOG_TAG,
-                "Exception occurred when executing API call: ${exception.message}"
-            )
-        }.getOrDefault(emptyList())
-    }
-
-    private suspend fun updateCachedPhotos(searchQuery: String) =
-        runCatching {
-            val response = api.search(searchQuery)
-            if (response.isSuccessful) {
-                response.body()?.let {
-                    cachedPhotos.clear()
-                    cachedPhotos.addAll(it.photosPage.photos)
-                }
-            } else {
-                throw Exception(
-                    "Flickr API responded with error: ${
-                        response.errorBody().toString()
-                    }"
-                )
-            }
-        }.onFailure { exception: Throwable ->
-            Log.d(
-                LOG_TAG,
-                "Exception occurred when executing API call: ${exception.message}"
-            )
+        val response = executeApiCall {
+            api.getRecent()
         }
+        return when (response) {
+            is ApiResponse.Success -> response.body
+            is ApiResponse.Error -> emptyList()
+        }
+    }
 }