From fddbd40b59bb1d88132a304ebaa67f657cc55a1d Mon Sep 17 00:00:00 2001 From: Denis Egorov Date: Fri, 11 Sep 2020 18:31:42 +0300 Subject: [PATCH 01/17] added customization of NetworkFetcher and NetworkCache --- .../main/java/com/airbnb/lottie/Lottie.java | 48 ++++++ .../lottie/LottieCompositionFactory.java | 32 ++-- .../java/com/airbnb/lottie/LottieConfig.java | 65 +++++++ .../airbnb/lottie/network/DefaultFetcher.java | 54 ++++++ .../com/airbnb/lottie/network/Fetcher.java | 12 ++ .../airbnb/lottie/network/NetworkCache.java | 13 +- .../airbnb/lottie/network/NetworkFetcher.java | 163 +++++++----------- .../com/airbnb/lottie/network/Result.java | 31 ++++ .../com/airbnb/lottie/network/Supplier.java | 5 + 9 files changed, 303 insertions(+), 120 deletions(-) create mode 100644 lottie/src/main/java/com/airbnb/lottie/Lottie.java create mode 100644 lottie/src/main/java/com/airbnb/lottie/LottieConfig.java create mode 100644 lottie/src/main/java/com/airbnb/lottie/network/DefaultFetcher.java create mode 100644 lottie/src/main/java/com/airbnb/lottie/network/Fetcher.java create mode 100644 lottie/src/main/java/com/airbnb/lottie/network/Result.java create mode 100644 lottie/src/main/java/com/airbnb/lottie/network/Supplier.java diff --git a/lottie/src/main/java/com/airbnb/lottie/Lottie.java b/lottie/src/main/java/com/airbnb/lottie/Lottie.java new file mode 100644 index 0000000000..749085d418 --- /dev/null +++ b/lottie/src/main/java/com/airbnb/lottie/Lottie.java @@ -0,0 +1,48 @@ +package com.airbnb.lottie; + +import android.content.Context; + +import com.airbnb.lottie.network.DefaultFetcher; +import com.airbnb.lottie.network.NetworkFetcher; +import com.airbnb.lottie.network.Fetcher; +import com.airbnb.lottie.network.NetworkCache; +import com.airbnb.lottie.network.Supplier; + +import java.io.File; + +import androidx.annotation.NonNull; + +public class Lottie { + + private static Fetcher fetcher; + private static Supplier cacheDirSupplier; + + public static void initialize(@NonNull final LottieConfig lottieConfig) { + fetcher = lottieConfig.networkFetcher; + if (fetcher == null) { + fetcher = new DefaultFetcher(); + } + cacheDirSupplier = lottieConfig.cacheDirSupplier; + if (cacheDirSupplier == null) { + cacheDirSupplier = new Supplier() { + @Override public File get() { + return new File(lottieConfig.applicationContext.getCacheDir(), "lottie_network_cache"); + } + }; + } + } + + @NonNull + public static NetworkFetcher networkFetcher(@NonNull Context context) { + return new NetworkFetcher(networkCache(context), fetcher != null ? fetcher : new DefaultFetcher()); + } + + @NonNull + public static NetworkCache networkCache(@NonNull final Context context) { + return new NetworkCache(cacheDirSupplier != null ? cacheDirSupplier : new Supplier() { + @Override public File get() { + return context.getCacheDir(); + } + }); + } +} \ No newline at end of file diff --git a/lottie/src/main/java/com/airbnb/lottie/LottieCompositionFactory.java b/lottie/src/main/java/com/airbnb/lottie/LottieCompositionFactory.java index 8d6fb95042..aaf34c102c 100644 --- a/lottie/src/main/java/com/airbnb/lottie/LottieCompositionFactory.java +++ b/lottie/src/main/java/com/airbnb/lottie/LottieCompositionFactory.java @@ -5,15 +5,13 @@ import android.content.res.Resources; import android.graphics.Bitmap; import android.graphics.BitmapFactory; -import android.os.Build; import com.airbnb.lottie.model.LottieCompositionCache; -import com.airbnb.lottie.network.NetworkCache; -import com.airbnb.lottie.network.NetworkFetcher; import com.airbnb.lottie.parser.LottieCompositionMoshiParser; import com.airbnb.lottie.parser.moshi.JsonReader; import com.airbnb.lottie.utils.Utils; + import org.json.JSONObject; import java.io.ByteArrayInputStream; @@ -65,14 +63,14 @@ public static void setMaxCacheSize(int size) { public static void clearCache(Context context) { taskCache.clear(); LottieCompositionCache.getInstance().clear(); - new NetworkCache(context).clear(); + Lottie.networkCache(context).clear(); } /** * Fetch an animation from an http url. Once it is downloaded once, Lottie will cache the file to disk for * future use. Because of this, you may call `fromUrl` ahead of time to warm the cache if you think you * might need an animation in the future. - * + *

* To skip the cache, add null as a third parameter. */ public static LottieTask fromUrl(final Context context, final String url) { @@ -88,7 +86,7 @@ public static LottieTask fromUrl(final Context context, final return cache(cacheKey, new Callable>() { @Override public LottieResult call() { - return NetworkFetcher.fetchSync(context, url, cacheKey); + return Lottie.networkFetcher(context).fetchSync(url, cacheKey); } }); } @@ -111,14 +109,14 @@ public static LottieResult fromUrlSync(Context context, Strin */ @WorkerThread public static LottieResult fromUrlSync(Context context, String url, @Nullable String cacheKey) { - return NetworkFetcher.fetchSync(context, url, cacheKey); + return Lottie.networkFetcher(context).fetchSync(url, cacheKey); } /** * Parse an animation from src/main/assets. It is recommended to use {@link #fromRawRes(Context, int)} instead. * The asset file name will be used as a cache key so future usages won't have to parse the json again. * However, if your animation has images, you may package the json and images as a single flattened zip file in assets. - * + *

* To skip the cache, add null as a third parameter. * * @see #fromZipStream(ZipInputStream, String) @@ -132,7 +130,7 @@ public static LottieTask fromAsset(Context context, final Str * Parse an animation from src/main/assets. It is recommended to use {@link #fromRawRes(Context, int)} instead. * The asset file name will be used as a cache key so future usages won't have to parse the json again. * However, if your animation has images, you may package the json and images as a single flattened zip file in assets. - * + *

* Pass null as the cache key to skip the cache. * * @see #fromZipStream(ZipInputStream, String) @@ -152,22 +150,22 @@ public LottieResult call() { * Parse an animation from src/main/assets. It is recommended to use {@link #fromRawRes(Context, int)} instead. * The asset file name will be used as a cache key so future usages won't have to parse the json again. * However, if your animation has images, you may package the json and images as a single flattened zip file in assets. - * + *

* To skip the cache, add null as a third parameter. * * @see #fromZipStreamSync(ZipInputStream, String) */ @WorkerThread public static LottieResult fromAssetSync(Context context, String fileName) { - String cacheKey = "asset_" + fileName; - return fromAssetSync(context, fileName, cacheKey); + String cacheKey = "asset_" + fileName; + return fromAssetSync(context, fileName, cacheKey); } /** * Parse an animation from src/main/assets. It is recommended to use {@link #fromRawRes(Context, int)} instead. * The asset file name will be used as a cache key so future usages won't have to parse the json again. * However, if your animation has images, you may package the json and images as a single flattened zip file in assets. - * + *

* Pass null as the cache key to skip the cache. * * @see #fromZipStreamSync(ZipInputStream, String) @@ -191,7 +189,7 @@ public static LottieResult fromAssetSync(Context context, Str * The resource id will be used as a cache key so future usages won't parse the json again. * Note: to correctly load dark mode (-night) resources, make sure you pass Activity as a context (instead of e.g. the application context). * The Activity won't be leaked. - * + *

* To skip the cache, add null as a third parameter. */ public static LottieTask fromRawRes(Context context, @RawRes final int rawRes) { @@ -204,7 +202,7 @@ public static LottieTask fromRawRes(Context context, @RawRes * The resource id will be used as a cache key so future usages won't parse the json again. * Note: to correctly load dark mode (-night) resources, make sure you pass Activity as a context (instead of e.g. the application context). * The Activity won't be leaked. - * + *

* Pass null as the cache key to skip caching. */ public static LottieTask fromRawRes(Context context, @RawRes final int rawRes, @Nullable final String cacheKey) { @@ -227,7 +225,7 @@ public LottieResult call() { * The resource id will be used as a cache key so future usages won't parse the json again. * Note: to correctly load dark mode (-night) resources, make sure you pass Activity as a context (instead of e.g. the application context). * The Activity won't be leaked. - * + *

* To skip the cache, add null as a third parameter. */ @WorkerThread @@ -241,7 +239,7 @@ public static LottieResult fromRawResSync(Context context, @R * The resource id will be used as a cache key so future usages won't parse the json again. * Note: to correctly load dark mode (-night) resources, make sure you pass Activity as a context (instead of e.g. the application context). * The Activity won't be leaked. - * + *

* Pass null as the cache key to skip caching. */ @WorkerThread diff --git a/lottie/src/main/java/com/airbnb/lottie/LottieConfig.java b/lottie/src/main/java/com/airbnb/lottie/LottieConfig.java new file mode 100644 index 0000000000..31876c5417 --- /dev/null +++ b/lottie/src/main/java/com/airbnb/lottie/LottieConfig.java @@ -0,0 +1,65 @@ +package com.airbnb.lottie; + +import android.content.Context; + +import com.airbnb.lottie.network.Fetcher; +import com.airbnb.lottie.network.Supplier; + +import java.io.File; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +public class LottieConfig { + + @NonNull final Context applicationContext; + @Nullable final Fetcher networkFetcher; + @Nullable final Supplier cacheDirSupplier; + + public LottieConfig(@NonNull Context applicationContext, @Nullable Fetcher networkFetcher, @Nullable Supplier cacheDirSupplier) { + this.applicationContext = applicationContext; + this.networkFetcher = networkFetcher; + this.cacheDirSupplier = cacheDirSupplier; + } + + public static final class Builder { + + @NonNull + private final Context context; + @Nullable + private Fetcher networkFetcher; + @Nullable + private Supplier cacheDirSupplier; + + public Builder(@NonNull Context context) { + this.context = context.getApplicationContext(); + } + + @NonNull + public Builder setNetworkFetcher(@NonNull Fetcher fetcher) { + this.networkFetcher = fetcher; + return this; + } + + @NonNull + public Builder setCacheDir(@NonNull final File file) { + this.cacheDirSupplier = new Supplier() { + @Override public File get() { + return file; + } + }; + return this; + } + + @NonNull + public Builder setCacheDirSupplier(@NonNull Supplier fileSupplier) { + this.cacheDirSupplier = fileSupplier; + return this; + } + + @NonNull + public LottieConfig build() { + return new LottieConfig(context, networkFetcher, cacheDirSupplier); + } + } +} \ No newline at end of file diff --git a/lottie/src/main/java/com/airbnb/lottie/network/DefaultFetcher.java b/lottie/src/main/java/com/airbnb/lottie/network/DefaultFetcher.java new file mode 100644 index 0000000000..6081637a01 --- /dev/null +++ b/lottie/src/main/java/com/airbnb/lottie/network/DefaultFetcher.java @@ -0,0 +1,54 @@ +package com.airbnb.lottie.network; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.HttpURLConnection; +import java.net.URL; + +import androidx.annotation.NonNull; + +public class DefaultFetcher implements Fetcher { + + @Override + @NonNull + public Result fetchSync(@NonNull String url) throws IOException { + HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection(); + connection.setRequestMethod("GET"); + + try { + connection.connect(); + + if (connection.getErrorStream() != null || connection.getResponseCode() != HttpURLConnection.HTTP_OK) { + String error = getErrorFromConnection(connection); + return new Result.Error("Unable to fetch " + url + ". Failed with " + connection.getResponseCode() + "\n" + error, + connection.getResponseCode()); + } + + return new Result.Success(connection.getInputStream(), connection.getContentType()); + } finally { + connection.disconnect(); + } + } + + private String getErrorFromConnection(HttpURLConnection connection) throws IOException { + BufferedReader r = new BufferedReader(new InputStreamReader(connection.getErrorStream())); + StringBuilder error = new StringBuilder(); + String line; + + try { + while ((line = r.readLine()) != null) { + error.append(line).append('\n'); + } + } catch (Exception e) { + throw e; + } finally { + try { + r.close(); + } catch (Exception e) { + // Do nothing. + } + } + return error.toString(); + } +} diff --git a/lottie/src/main/java/com/airbnb/lottie/network/Fetcher.java b/lottie/src/main/java/com/airbnb/lottie/network/Fetcher.java new file mode 100644 index 0000000000..df2f11cfaa --- /dev/null +++ b/lottie/src/main/java/com/airbnb/lottie/network/Fetcher.java @@ -0,0 +1,12 @@ +package com.airbnb.lottie.network; + +import java.io.IOException; + +import androidx.annotation.NonNull; +import androidx.annotation.WorkerThread; + +public interface Fetcher { + @WorkerThread + @NonNull + Result fetchSync(@NonNull String url) throws IOException; +} diff --git a/lottie/src/main/java/com/airbnb/lottie/network/NetworkCache.java b/lottie/src/main/java/com/airbnb/lottie/network/NetworkCache.java index 71efef2865..9dbd4ee0ad 100644 --- a/lottie/src/main/java/com/airbnb/lottie/network/NetworkCache.java +++ b/lottie/src/main/java/com/airbnb/lottie/network/NetworkCache.java @@ -1,6 +1,7 @@ package com.airbnb.lottie.network; -import android.content.Context; + +import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.WorkerThread; import androidx.core.util.Pair; @@ -19,10 +20,12 @@ * Helper class to save and restore animations fetched from an URL to the app disk cache. */ public class NetworkCache { - private final Context appContext; - public NetworkCache(Context appContext) { - this.appContext = appContext.getApplicationContext(); + @NonNull + private final Supplier cacheDir; + + public NetworkCache(@NonNull Supplier cacheDir) { + this.cacheDir = cacheDir; } public void clear() { @@ -139,7 +142,7 @@ private File getCachedFile(String url) throws FileNotFoundException { } private File parentDir() { - File file = new File(appContext.getCacheDir(), "lottie_network_cache"); + File file= cacheDir.get(); if (file.isFile()) { file.delete(); } diff --git a/lottie/src/main/java/com/airbnb/lottie/network/NetworkFetcher.java b/lottie/src/main/java/com/airbnb/lottie/network/NetworkFetcher.java index 2f7463373b..e5007848fd 100644 --- a/lottie/src/main/java/com/airbnb/lottie/network/NetworkFetcher.java +++ b/lottie/src/main/java/com/airbnb/lottie/network/NetworkFetcher.java @@ -1,64 +1,54 @@ package com.airbnb.lottie.network; -import android.content.Context; -import androidx.annotation.Nullable; -import androidx.annotation.WorkerThread; -import androidx.core.util.Pair; - import com.airbnb.lottie.LottieComposition; import com.airbnb.lottie.LottieCompositionFactory; import com.airbnb.lottie.LottieResult; import com.airbnb.lottie.utils.Logger; -import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; -import java.io.InputStreamReader; -import java.net.HttpURLConnection; -import java.net.URL; -import java.util.zip.ZipInputStream; -public class NetworkFetcher { +import java.util.zip.ZipInputStream; - private final Context appContext; - private final String url; +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.annotation.WorkerThread; +import androidx.core.util.Pair; - @Nullable private final NetworkCache networkCache; +public class NetworkFetcher { - public static LottieResult fetchSync(Context context, String url, @Nullable String cacheKey) { - return new NetworkFetcher(context, url, cacheKey).fetchSync(); - } + @NonNull + private final NetworkCache networkCache; + @NonNull + private final Fetcher fetcher; - private NetworkFetcher(Context context, String url, @Nullable String cacheKey) { - appContext = context.getApplicationContext(); - this.url = url; - if (cacheKey == null) { - networkCache = null; - } else { - networkCache = new NetworkCache(appContext); - } + public NetworkFetcher(@NonNull NetworkCache networkCache, @NonNull Fetcher fetcher) { + this.networkCache = networkCache; + this.fetcher = fetcher; } - @WorkerThread - public LottieResult fetchSync() { - LottieComposition result = fetchFromCache(); + @NonNull + public LottieResult fetchSync(@NonNull String url, @Nullable String cacheKey) { + LottieComposition result = fetchFromCache(url, cacheKey); if (result != null) { return new LottieResult<>(result); } Logger.debug("Animation for " + url + " not found in cache. Fetching from network."); - return fetchFromNetwork(); + + try { + return fetchFromNetwork(url, cacheKey); + } catch (IOException e) { + return new LottieResult<>(e); + } } - /** - * Returns null if the animation doesn't exist in the cache. - */ @Nullable @WorkerThread - private LottieComposition fetchFromCache() { - if (networkCache == null) { + private LottieComposition fetchFromCache(@NonNull String url, @Nullable String cacheKey) { + if (cacheKey == null) { return null; } Pair cacheResult = networkCache.fetch(url); @@ -80,69 +70,35 @@ private LottieComposition fetchFromCache() { return null; } + @NonNull @WorkerThread - private LottieResult fetchFromNetwork() { - try { - return fetchFromNetworkInternal(); - } catch (IOException e) { - return new LottieResult<>(e); - } - } - - @WorkerThread - private LottieResult fetchFromNetworkInternal() throws IOException { + private LottieResult fetchFromNetwork(@NonNull String url, @Nullable String cacheKey) throws IOException { Logger.debug("Fetching " + url); - - HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection(); - connection.setRequestMethod("GET"); - try { - connection.connect(); - - if (connection.getErrorStream() != null || connection.getResponseCode() != HttpURLConnection.HTTP_OK) { - String error = getErrorFromConnection(connection); - return new LottieResult(new IllegalArgumentException("Unable to fetch " + url + ". Failed with " + connection.getResponseCode() + "\n" + error)); + Result fetchResult = fetcher.fetchSync(url); + if (fetchResult instanceof Result.Success) { + InputStream inputStream = ((Result.Success) fetchResult).inputStream; + String contentType = ((Result.Success) fetchResult).contentType; + LottieResult result = fromInputStream(url, inputStream, contentType, cacheKey); + Logger.debug("Completed fetch from network. Success: " + (result.getValue() != null)); + return result; + } else { + String error = ((Result.Error) fetchResult).message; + int responseCode = ((Result.Error) fetchResult).responseCode; + return new LottieResult<>( + new IllegalArgumentException("Unable to fetch " + url + ". Failed with " + responseCode + "\n" + error)); } - - LottieResult result = getResultFromConnection(connection); - Logger.debug("Completed fetch from network. Success: " + (result.getValue() != null)); - return result; } catch (Exception e) { return new LottieResult<>(e); - } finally { - connection.disconnect(); - } - } - - private String getErrorFromConnection(HttpURLConnection connection) throws IOException { - int responseCode = connection.getResponseCode(); - BufferedReader r = new BufferedReader(new InputStreamReader(connection.getErrorStream())); - StringBuilder error = new StringBuilder(); - String line; - - try { - while ((line = r.readLine()) != null) { - error.append(line).append('\n'); - } - } catch (Exception e) { - throw e; - } finally { - try { - r.close(); - } catch (Exception e) { - // Do nothing. - } } - return error.toString(); } - @Nullable - private LottieResult getResultFromConnection(HttpURLConnection connection) throws IOException { - File file; + @NonNull + private LottieResult fromInputStream(@NonNull String url, @NonNull InputStream inputStream, @Nullable String contentType, + @Nullable String cacheKey) throws IOException { FileExtension extension; LottieResult result; - String contentType = connection.getContentType(); if (contentType == null) { // Assume JSON for best effort parsing. If it fails, it will just deliver the parse exception // in the result which is more useful than failing here. @@ -151,26 +107,37 @@ private LottieResult getResultFromConnection(HttpURLConnectio if (contentType.contains("application/zip")) { Logger.debug("Handling zip response."); extension = FileExtension.ZIP; - if (networkCache == null) { - result = LottieCompositionFactory.fromZipStreamSync(new ZipInputStream(connection.getInputStream()), null); - } else { - file = networkCache.writeTempCacheFile(url, connection.getInputStream(), extension); - result = LottieCompositionFactory.fromZipStreamSync(new ZipInputStream(new FileInputStream(file)), url); - } + result = fromZipStream(url, inputStream, cacheKey); } else { Logger.debug("Received json response."); extension = FileExtension.JSON; - if (networkCache == null) { - result = LottieCompositionFactory.fromJsonInputStreamSync(connection.getInputStream(), null); - } else { - file = networkCache.writeTempCacheFile(url, connection.getInputStream(), extension); - result = LottieCompositionFactory.fromJsonInputStreamSync(new FileInputStream(new File(file.getAbsolutePath())), url); - } + result = fromJsonStream(url, inputStream, cacheKey); } - if (networkCache != null && result.getValue() != null) { + if (cacheKey != null && result.getValue() != null) { networkCache.renameTempFile(url, extension); } + return result; } + + @NonNull + private LottieResult fromZipStream(@NonNull String url, @NonNull InputStream inputStream, @Nullable String cacheKey) + throws IOException { + if (cacheKey == null) { + return LottieCompositionFactory.fromZipStreamSync(new ZipInputStream(inputStream), null); + } + File file = networkCache.writeTempCacheFile(url, inputStream, FileExtension.ZIP); + return LottieCompositionFactory.fromZipStreamSync(new ZipInputStream(new FileInputStream(file)), url); + } + + @NonNull + private LottieResult fromJsonStream(@NonNull String url, @NonNull InputStream inputStream, @Nullable String cacheKey) + throws IOException { + if (cacheKey == null) { + return LottieCompositionFactory.fromJsonInputStreamSync(inputStream, null); + } + File file = networkCache.writeTempCacheFile(url, inputStream, FileExtension.JSON); + return LottieCompositionFactory.fromJsonInputStreamSync(new FileInputStream(new File(file.getAbsolutePath())), url); + } } diff --git a/lottie/src/main/java/com/airbnb/lottie/network/Result.java b/lottie/src/main/java/com/airbnb/lottie/network/Result.java new file mode 100644 index 0000000000..cf933731be --- /dev/null +++ b/lottie/src/main/java/com/airbnb/lottie/network/Result.java @@ -0,0 +1,31 @@ +package com.airbnb.lottie.network; + +import java.io.InputStream; + +import androidx.annotation.NonNull; + +public class Result { + + public static class Success extends Result { + @NonNull + public final InputStream inputStream; + @NonNull + public final String contentType; + + public Success(@NonNull InputStream inputStream, @NonNull String contentType) { + this.inputStream = inputStream; + this.contentType = contentType; + } + } + + public static class Error extends Result { + @NonNull + public final String message; + public final int responseCode; + + public Error(@NonNull String message, int responseCode) { + this.message = message; + this.responseCode = responseCode; + } + } +} diff --git a/lottie/src/main/java/com/airbnb/lottie/network/Supplier.java b/lottie/src/main/java/com/airbnb/lottie/network/Supplier.java new file mode 100644 index 0000000000..4666e129fe --- /dev/null +++ b/lottie/src/main/java/com/airbnb/lottie/network/Supplier.java @@ -0,0 +1,5 @@ +package com.airbnb.lottie.network; + +public interface Supplier { + T get(); +} \ No newline at end of file From a082a50bd0c0fb68c9f97c83a4d47cf5f80c608e Mon Sep 17 00:00:00 2001 From: Denis Egorov Date: Fri, 11 Sep 2020 18:48:22 +0300 Subject: [PATCH 02/17] added customization of NetworkFetcher and NetworkCache --- lottie/src/main/java/com/airbnb/lottie/Lottie.java | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/lottie/src/main/java/com/airbnb/lottie/Lottie.java b/lottie/src/main/java/com/airbnb/lottie/Lottie.java index 749085d418..9b0a7f2b59 100644 --- a/lottie/src/main/java/com/airbnb/lottie/Lottie.java +++ b/lottie/src/main/java/com/airbnb/lottie/Lottie.java @@ -19,17 +19,7 @@ public class Lottie { public static void initialize(@NonNull final LottieConfig lottieConfig) { fetcher = lottieConfig.networkFetcher; - if (fetcher == null) { - fetcher = new DefaultFetcher(); - } cacheDirSupplier = lottieConfig.cacheDirSupplier; - if (cacheDirSupplier == null) { - cacheDirSupplier = new Supplier() { - @Override public File get() { - return new File(lottieConfig.applicationContext.getCacheDir(), "lottie_network_cache"); - } - }; - } } @NonNull From d9c9d4b48111b5af86b75db49c1047cf2a86bc06 Mon Sep 17 00:00:00 2001 From: Denis Egorov Date: Fri, 11 Sep 2020 18:55:42 +0300 Subject: [PATCH 03/17] added customization of NetworkFetcher and NetworkCache --- .../src/main/java/com/airbnb/lottie/network/NetworkFetcher.java | 1 + 1 file changed, 1 insertion(+) diff --git a/lottie/src/main/java/com/airbnb/lottie/network/NetworkFetcher.java b/lottie/src/main/java/com/airbnb/lottie/network/NetworkFetcher.java index e5007848fd..53cb4d9adf 100644 --- a/lottie/src/main/java/com/airbnb/lottie/network/NetworkFetcher.java +++ b/lottie/src/main/java/com/airbnb/lottie/network/NetworkFetcher.java @@ -30,6 +30,7 @@ public NetworkFetcher(@NonNull NetworkCache networkCache, @NonNull Fetcher fetch } @NonNull + @WorkerThread public LottieResult fetchSync(@NonNull String url, @Nullable String cacheKey) { LottieComposition result = fetchFromCache(url, cacheKey); if (result != null) { From b5bda21193e6292e4ec037d27bc6318fa376991b Mon Sep 17 00:00:00 2001 From: Denis Egorov Date: Fri, 11 Sep 2020 19:12:41 +0300 Subject: [PATCH 04/17] added customization of NetworkFetcher and NetworkCache --- .../main/java/com/airbnb/lottie/Lottie.java | 12 +++++------ .../java/com/airbnb/lottie/LottieConfig.java | 20 +++++++++---------- .../airbnb/lottie/network/CacheProvider.java | 9 +++++++++ .../airbnb/lottie/network/NetworkCache.java | 6 +++--- .../airbnb/lottie/network/NetworkFetcher.java | 8 ++------ .../com/airbnb/lottie/network/Supplier.java | 5 ----- 6 files changed, 30 insertions(+), 30 deletions(-) create mode 100644 lottie/src/main/java/com/airbnb/lottie/network/CacheProvider.java delete mode 100644 lottie/src/main/java/com/airbnb/lottie/network/Supplier.java diff --git a/lottie/src/main/java/com/airbnb/lottie/Lottie.java b/lottie/src/main/java/com/airbnb/lottie/Lottie.java index 9b0a7f2b59..3592730e17 100644 --- a/lottie/src/main/java/com/airbnb/lottie/Lottie.java +++ b/lottie/src/main/java/com/airbnb/lottie/Lottie.java @@ -6,7 +6,7 @@ import com.airbnb.lottie.network.NetworkFetcher; import com.airbnb.lottie.network.Fetcher; import com.airbnb.lottie.network.NetworkCache; -import com.airbnb.lottie.network.Supplier; +import com.airbnb.lottie.network.CacheProvider; import java.io.File; @@ -15,11 +15,11 @@ public class Lottie { private static Fetcher fetcher; - private static Supplier cacheDirSupplier; + private static CacheProvider cacheDirCacheProvider; public static void initialize(@NonNull final LottieConfig lottieConfig) { fetcher = lottieConfig.networkFetcher; - cacheDirSupplier = lottieConfig.cacheDirSupplier; + cacheDirCacheProvider = lottieConfig.cacheDirCacheProvider; } @NonNull @@ -29,9 +29,9 @@ public static NetworkFetcher networkFetcher(@NonNull Context context) { @NonNull public static NetworkCache networkCache(@NonNull final Context context) { - return new NetworkCache(cacheDirSupplier != null ? cacheDirSupplier : new Supplier() { - @Override public File get() { - return context.getCacheDir(); + return new NetworkCache(cacheDirCacheProvider != null ? cacheDirCacheProvider : new CacheProvider() { + @Override @NonNull public File getCacheDir() { + return new File(context.getCacheDir(), "lottie_network_cache"); } }); } diff --git a/lottie/src/main/java/com/airbnb/lottie/LottieConfig.java b/lottie/src/main/java/com/airbnb/lottie/LottieConfig.java index 31876c5417..140cf478f6 100644 --- a/lottie/src/main/java/com/airbnb/lottie/LottieConfig.java +++ b/lottie/src/main/java/com/airbnb/lottie/LottieConfig.java @@ -3,7 +3,7 @@ import android.content.Context; import com.airbnb.lottie.network.Fetcher; -import com.airbnb.lottie.network.Supplier; +import com.airbnb.lottie.network.CacheProvider; import java.io.File; @@ -14,12 +14,12 @@ public class LottieConfig { @NonNull final Context applicationContext; @Nullable final Fetcher networkFetcher; - @Nullable final Supplier cacheDirSupplier; + @Nullable final CacheProvider cacheDirCacheProvider; - public LottieConfig(@NonNull Context applicationContext, @Nullable Fetcher networkFetcher, @Nullable Supplier cacheDirSupplier) { + public LottieConfig(@NonNull Context applicationContext, @Nullable Fetcher networkFetcher, @Nullable CacheProvider cacheDirCacheProvider) { this.applicationContext = applicationContext; this.networkFetcher = networkFetcher; - this.cacheDirSupplier = cacheDirSupplier; + this.cacheDirCacheProvider = cacheDirCacheProvider; } public static final class Builder { @@ -29,7 +29,7 @@ public static final class Builder { @Nullable private Fetcher networkFetcher; @Nullable - private Supplier cacheDirSupplier; + private CacheProvider cacheDirCacheProvider; public Builder(@NonNull Context context) { this.context = context.getApplicationContext(); @@ -43,8 +43,8 @@ public Builder setNetworkFetcher(@NonNull Fetcher fetcher) { @NonNull public Builder setCacheDir(@NonNull final File file) { - this.cacheDirSupplier = new Supplier() { - @Override public File get() { + this.cacheDirCacheProvider = new CacheProvider() { + @Override @NonNull public File getCacheDir() { return file; } }; @@ -52,14 +52,14 @@ public Builder setCacheDir(@NonNull final File file) { } @NonNull - public Builder setCacheDirSupplier(@NonNull Supplier fileSupplier) { - this.cacheDirSupplier = fileSupplier; + public Builder setCacheDirCacheProvider(@NonNull CacheProvider fileCacheProvider) { + this.cacheDirCacheProvider = fileCacheProvider; return this; } @NonNull public LottieConfig build() { - return new LottieConfig(context, networkFetcher, cacheDirSupplier); + return new LottieConfig(context, networkFetcher, cacheDirCacheProvider); } } } \ No newline at end of file diff --git a/lottie/src/main/java/com/airbnb/lottie/network/CacheProvider.java b/lottie/src/main/java/com/airbnb/lottie/network/CacheProvider.java new file mode 100644 index 0000000000..4d9e96d5b3 --- /dev/null +++ b/lottie/src/main/java/com/airbnb/lottie/network/CacheProvider.java @@ -0,0 +1,9 @@ +package com.airbnb.lottie.network; + +import java.io.File; + +import androidx.annotation.NonNull; + +public interface CacheProvider { + @NonNull File getCacheDir(); +} \ No newline at end of file diff --git a/lottie/src/main/java/com/airbnb/lottie/network/NetworkCache.java b/lottie/src/main/java/com/airbnb/lottie/network/NetworkCache.java index 9dbd4ee0ad..feb370a977 100644 --- a/lottie/src/main/java/com/airbnb/lottie/network/NetworkCache.java +++ b/lottie/src/main/java/com/airbnb/lottie/network/NetworkCache.java @@ -22,9 +22,9 @@ public class NetworkCache { @NonNull - private final Supplier cacheDir; + private final CacheProvider cacheDir; - public NetworkCache(@NonNull Supplier cacheDir) { + public NetworkCache(@NonNull CacheProvider cacheDir) { this.cacheDir = cacheDir; } @@ -142,7 +142,7 @@ private File getCachedFile(String url) throws FileNotFoundException { } private File parentDir() { - File file= cacheDir.get(); + File file= cacheDir.getCacheDir(); if (file.isFile()) { file.delete(); } diff --git a/lottie/src/main/java/com/airbnb/lottie/network/NetworkFetcher.java b/lottie/src/main/java/com/airbnb/lottie/network/NetworkFetcher.java index 53cb4d9adf..c7c1a06046 100644 --- a/lottie/src/main/java/com/airbnb/lottie/network/NetworkFetcher.java +++ b/lottie/src/main/java/com/airbnb/lottie/network/NetworkFetcher.java @@ -39,11 +39,7 @@ public LottieResult fetchSync(@NonNull String url, @Nullable Logger.debug("Animation for " + url + " not found in cache. Fetching from network."); - try { - return fetchFromNetwork(url, cacheKey); - } catch (IOException e) { - return new LottieResult<>(e); - } + return fetchFromNetwork(url, cacheKey); } @Nullable @@ -73,7 +69,7 @@ private LottieComposition fetchFromCache(@NonNull String url, @Nullable String c @NonNull @WorkerThread - private LottieResult fetchFromNetwork(@NonNull String url, @Nullable String cacheKey) throws IOException { + private LottieResult fetchFromNetwork(@NonNull String url, @Nullable String cacheKey) { Logger.debug("Fetching " + url); try { diff --git a/lottie/src/main/java/com/airbnb/lottie/network/Supplier.java b/lottie/src/main/java/com/airbnb/lottie/network/Supplier.java deleted file mode 100644 index 4666e129fe..0000000000 --- a/lottie/src/main/java/com/airbnb/lottie/network/Supplier.java +++ /dev/null @@ -1,5 +0,0 @@ -package com.airbnb.lottie.network; - -public interface Supplier { - T get(); -} \ No newline at end of file From 0fd9dd328456d155cf9cf793ee9d1f1033eb8e83 Mon Sep 17 00:00:00 2001 From: Denis Egorov Date: Fri, 11 Sep 2020 19:24:47 +0300 Subject: [PATCH 05/17] added customization of NetworkFetcher and NetworkCache --- .../main/java/com/airbnb/lottie/Lottie.java | 31 ++++++++++++++++--- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/lottie/src/main/java/com/airbnb/lottie/Lottie.java b/lottie/src/main/java/com/airbnb/lottie/Lottie.java index 3592730e17..08fe03a61f 100644 --- a/lottie/src/main/java/com/airbnb/lottie/Lottie.java +++ b/lottie/src/main/java/com/airbnb/lottie/Lottie.java @@ -17,6 +17,9 @@ public class Lottie { private static Fetcher fetcher; private static CacheProvider cacheDirCacheProvider; + private static volatile NetworkFetcher networkFetcher; + private static volatile NetworkCache networkCache; + public static void initialize(@NonNull final LottieConfig lottieConfig) { fetcher = lottieConfig.networkFetcher; cacheDirCacheProvider = lottieConfig.cacheDirCacheProvider; @@ -24,15 +27,33 @@ public static void initialize(@NonNull final LottieConfig lottieConfig) { @NonNull public static NetworkFetcher networkFetcher(@NonNull Context context) { - return new NetworkFetcher(networkCache(context), fetcher != null ? fetcher : new DefaultFetcher()); + NetworkFetcher local = networkFetcher; + if (local == null) { + synchronized (NetworkFetcher.class) { + local = networkFetcher; + if (local == null) { + networkFetcher = local = new NetworkFetcher(networkCache(context), fetcher != null ? fetcher : new DefaultFetcher()); + } + } + } + return local; } @NonNull public static NetworkCache networkCache(@NonNull final Context context) { - return new NetworkCache(cacheDirCacheProvider != null ? cacheDirCacheProvider : new CacheProvider() { - @Override @NonNull public File getCacheDir() { - return new File(context.getCacheDir(), "lottie_network_cache"); + NetworkCache local = networkCache; + if (local == null) { + synchronized (NetworkCache.class) { + local = networkCache; + if (local == null) { + networkCache = local = new NetworkCache(cacheDirCacheProvider != null ? cacheDirCacheProvider : new CacheProvider() { + @Override @NonNull public File getCacheDir() { + return new File(context.getCacheDir(), "lottie_network_cache"); + } + }); + } } - }); + } + return local; } } \ No newline at end of file From 8992855a62601766e864f08a0262b20122f3751e Mon Sep 17 00:00:00 2001 From: Denis Egorov Date: Mon, 14 Sep 2020 13:16:05 +0300 Subject: [PATCH 06/17] fix --- lottie/src/main/java/com/airbnb/lottie/L.java | 57 +++++++++++++++++++ .../main/java/com/airbnb/lottie/Lottie.java | 56 +++--------------- .../lottie/LottieCompositionFactory.java | 6 +- .../java/com/airbnb/lottie/LottieConfig.java | 19 ++++--- .../airbnb/lottie/network/CacheProvider.java | 9 +++ .../airbnb/lottie/network/DefaultFetcher.java | 6 +- .../com/airbnb/lottie/network/Fetcher.java | 5 +- .../{Result.java => LottieNetworkResult.java} | 6 +- .../airbnb/lottie/network/NetworkCache.java | 2 +- .../airbnb/lottie/network/NetworkFetcher.java | 12 ++-- 10 files changed, 104 insertions(+), 74 deletions(-) rename lottie/src/main/java/com/airbnb/lottie/network/{Result.java => LottieNetworkResult.java} (78%) diff --git a/lottie/src/main/java/com/airbnb/lottie/L.java b/lottie/src/main/java/com/airbnb/lottie/L.java index f26b6aeac8..eab00dde44 100644 --- a/lottie/src/main/java/com/airbnb/lottie/L.java +++ b/lottie/src/main/java/com/airbnb/lottie/L.java @@ -1,5 +1,16 @@ package com.airbnb.lottie; +import android.content.Context; + +import com.airbnb.lottie.network.CacheProvider; +import com.airbnb.lottie.network.DefaultFetcher; +import com.airbnb.lottie.network.Fetcher; +import com.airbnb.lottie.network.NetworkCache; +import com.airbnb.lottie.network.NetworkFetcher; + +import java.io.File; + +import androidx.annotation.NonNull; import androidx.annotation.RestrictTo; import androidx.core.os.TraceCompat; @@ -16,6 +27,12 @@ public class L { private static int traceDepth = 0; private static int depthPastMaxDepth = 0; + private static Fetcher fetcher; + private static CacheProvider cacheProvider; + + private static volatile NetworkFetcher networkFetcher; + private static volatile NetworkCache networkCache; + public static void setTraceEnabled(boolean enabled) { if (traceEnabled == enabled) { return; @@ -60,4 +77,44 @@ public static float endSection(String section) { TraceCompat.endSection(); return (System.nanoTime() - startTimeNs[traceDepth]) / 1000000f; } + + public static void setFetcher(Fetcher customFetcher) { + fetcher = customFetcher; + } + + public static void setCacheProvider(CacheProvider customProvider) { + cacheProvider = customProvider; + } + + @NonNull + public static NetworkFetcher networkFetcher(@NonNull Context context) { + NetworkFetcher local = networkFetcher; + if (local == null) { + synchronized (NetworkFetcher.class) { + local = networkFetcher; + if (local == null) { + networkFetcher = local = new NetworkFetcher(networkCache(context), fetcher != null ? fetcher : new DefaultFetcher()); + } + } + } + return local; + } + + @NonNull + public static NetworkCache networkCache(@NonNull final Context context) { + NetworkCache local = networkCache; + if (local == null) { + synchronized (NetworkCache.class) { + local = networkCache; + if (local == null) { + networkCache = local = new NetworkCache(cacheProvider != null ? cacheProvider : new CacheProvider() { + @Override @NonNull public File getCacheDir() { + return new File(context.getCacheDir(), "lottie_network_cache"); + } + }); + } + } + } + return local; + } } diff --git a/lottie/src/main/java/com/airbnb/lottie/Lottie.java b/lottie/src/main/java/com/airbnb/lottie/Lottie.java index 08fe03a61f..96c7a6f255 100644 --- a/lottie/src/main/java/com/airbnb/lottie/Lottie.java +++ b/lottie/src/main/java/com/airbnb/lottie/Lottie.java @@ -1,59 +1,17 @@ package com.airbnb.lottie; -import android.content.Context; - -import com.airbnb.lottie.network.DefaultFetcher; -import com.airbnb.lottie.network.NetworkFetcher; -import com.airbnb.lottie.network.Fetcher; -import com.airbnb.lottie.network.NetworkCache; -import com.airbnb.lottie.network.CacheProvider; - -import java.io.File; - import androidx.annotation.NonNull; +/** + * Class for initializing the library with custom config + */ public class Lottie { - private static Fetcher fetcher; - private static CacheProvider cacheDirCacheProvider; - - private static volatile NetworkFetcher networkFetcher; - private static volatile NetworkCache networkCache; - - public static void initialize(@NonNull final LottieConfig lottieConfig) { - fetcher = lottieConfig.networkFetcher; - cacheDirCacheProvider = lottieConfig.cacheDirCacheProvider; - } - - @NonNull - public static NetworkFetcher networkFetcher(@NonNull Context context) { - NetworkFetcher local = networkFetcher; - if (local == null) { - synchronized (NetworkFetcher.class) { - local = networkFetcher; - if (local == null) { - networkFetcher = local = new NetworkFetcher(networkCache(context), fetcher != null ? fetcher : new DefaultFetcher()); - } - } - } - return local; + private Lottie() { } - @NonNull - public static NetworkCache networkCache(@NonNull final Context context) { - NetworkCache local = networkCache; - if (local == null) { - synchronized (NetworkCache.class) { - local = networkCache; - if (local == null) { - networkCache = local = new NetworkCache(cacheDirCacheProvider != null ? cacheDirCacheProvider : new CacheProvider() { - @Override @NonNull public File getCacheDir() { - return new File(context.getCacheDir(), "lottie_network_cache"); - } - }); - } - } - } - return local; + public static void initialize(@NonNull final LottieConfig lottieConfig) { + L.setFetcher(lottieConfig.networkFetcher); + L.setCacheProvider(lottieConfig.cacheProvider); } } \ No newline at end of file diff --git a/lottie/src/main/java/com/airbnb/lottie/LottieCompositionFactory.java b/lottie/src/main/java/com/airbnb/lottie/LottieCompositionFactory.java index aaf34c102c..f4a1a6ab69 100644 --- a/lottie/src/main/java/com/airbnb/lottie/LottieCompositionFactory.java +++ b/lottie/src/main/java/com/airbnb/lottie/LottieCompositionFactory.java @@ -63,7 +63,7 @@ public static void setMaxCacheSize(int size) { public static void clearCache(Context context) { taskCache.clear(); LottieCompositionCache.getInstance().clear(); - Lottie.networkCache(context).clear(); + L.networkCache(context).clear(); } /** @@ -86,7 +86,7 @@ public static LottieTask fromUrl(final Context context, final return cache(cacheKey, new Callable>() { @Override public LottieResult call() { - return Lottie.networkFetcher(context).fetchSync(url, cacheKey); + return L.networkFetcher(context).fetchSync(url, cacheKey); } }); } @@ -109,7 +109,7 @@ public static LottieResult fromUrlSync(Context context, Strin */ @WorkerThread public static LottieResult fromUrlSync(Context context, String url, @Nullable String cacheKey) { - return Lottie.networkFetcher(context).fetchSync(url, cacheKey); + return L.networkFetcher(context).fetchSync(url, cacheKey); } /** diff --git a/lottie/src/main/java/com/airbnb/lottie/LottieConfig.java b/lottie/src/main/java/com/airbnb/lottie/LottieConfig.java index 140cf478f6..e9dc13e160 100644 --- a/lottie/src/main/java/com/airbnb/lottie/LottieConfig.java +++ b/lottie/src/main/java/com/airbnb/lottie/LottieConfig.java @@ -10,16 +10,19 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; +/** + * Class for custom library configuration + */ public class LottieConfig { @NonNull final Context applicationContext; @Nullable final Fetcher networkFetcher; - @Nullable final CacheProvider cacheDirCacheProvider; + @Nullable final CacheProvider cacheProvider; - public LottieConfig(@NonNull Context applicationContext, @Nullable Fetcher networkFetcher, @Nullable CacheProvider cacheDirCacheProvider) { + public LottieConfig(@NonNull Context applicationContext, @Nullable Fetcher networkFetcher, @Nullable CacheProvider cacheProvider) { this.applicationContext = applicationContext; this.networkFetcher = networkFetcher; - this.cacheDirCacheProvider = cacheDirCacheProvider; + this.cacheProvider = cacheProvider; } public static final class Builder { @@ -29,7 +32,7 @@ public static final class Builder { @Nullable private Fetcher networkFetcher; @Nullable - private CacheProvider cacheDirCacheProvider; + private CacheProvider cacheProvider; public Builder(@NonNull Context context) { this.context = context.getApplicationContext(); @@ -43,7 +46,7 @@ public Builder setNetworkFetcher(@NonNull Fetcher fetcher) { @NonNull public Builder setCacheDir(@NonNull final File file) { - this.cacheDirCacheProvider = new CacheProvider() { + this.cacheProvider = new CacheProvider() { @Override @NonNull public File getCacheDir() { return file; } @@ -52,14 +55,14 @@ public Builder setCacheDir(@NonNull final File file) { } @NonNull - public Builder setCacheDirCacheProvider(@NonNull CacheProvider fileCacheProvider) { - this.cacheDirCacheProvider = fileCacheProvider; + public Builder setCacheProvider(@NonNull CacheProvider fileCacheProvider) { + this.cacheProvider = fileCacheProvider; return this; } @NonNull public LottieConfig build() { - return new LottieConfig(context, networkFetcher, cacheDirCacheProvider); + return new LottieConfig(context, networkFetcher, cacheProvider); } } } \ No newline at end of file diff --git a/lottie/src/main/java/com/airbnb/lottie/network/CacheProvider.java b/lottie/src/main/java/com/airbnb/lottie/network/CacheProvider.java index 4d9e96d5b3..c55fe8bae5 100644 --- a/lottie/src/main/java/com/airbnb/lottie/network/CacheProvider.java +++ b/lottie/src/main/java/com/airbnb/lottie/network/CacheProvider.java @@ -4,6 +4,15 @@ import androidx.annotation.NonNull; +/** + * Interface for providing the custom cache directory + */ public interface CacheProvider { + + /** + * Called during cache operations + * + * @return cache directory + */ @NonNull File getCacheDir(); } \ No newline at end of file diff --git a/lottie/src/main/java/com/airbnb/lottie/network/DefaultFetcher.java b/lottie/src/main/java/com/airbnb/lottie/network/DefaultFetcher.java index 6081637a01..3b10c52a37 100644 --- a/lottie/src/main/java/com/airbnb/lottie/network/DefaultFetcher.java +++ b/lottie/src/main/java/com/airbnb/lottie/network/DefaultFetcher.java @@ -12,7 +12,7 @@ public class DefaultFetcher implements Fetcher { @Override @NonNull - public Result fetchSync(@NonNull String url) throws IOException { + public LottieNetworkResult fetchSync(@NonNull String url) throws IOException { HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection(); connection.setRequestMethod("GET"); @@ -21,11 +21,11 @@ public Result fetchSync(@NonNull String url) throws IOException { if (connection.getErrorStream() != null || connection.getResponseCode() != HttpURLConnection.HTTP_OK) { String error = getErrorFromConnection(connection); - return new Result.Error("Unable to fetch " + url + ". Failed with " + connection.getResponseCode() + "\n" + error, + return new LottieNetworkResult.Error("Unable to fetch " + url + ". Failed with " + connection.getResponseCode() + "\n" + error, connection.getResponseCode()); } - return new Result.Success(connection.getInputStream(), connection.getContentType()); + return new LottieNetworkResult.Success(connection.getInputStream(), connection.getContentType()); } finally { connection.disconnect(); } diff --git a/lottie/src/main/java/com/airbnb/lottie/network/Fetcher.java b/lottie/src/main/java/com/airbnb/lottie/network/Fetcher.java index df2f11cfaa..bbbb2e5dcc 100644 --- a/lottie/src/main/java/com/airbnb/lottie/network/Fetcher.java +++ b/lottie/src/main/java/com/airbnb/lottie/network/Fetcher.java @@ -5,8 +5,11 @@ import androidx.annotation.NonNull; import androidx.annotation.WorkerThread; +/** + * Interface for custom fetcher + */ public interface Fetcher { @WorkerThread @NonNull - Result fetchSync(@NonNull String url) throws IOException; + LottieNetworkResult fetchSync(@NonNull String url) throws IOException; } diff --git a/lottie/src/main/java/com/airbnb/lottie/network/Result.java b/lottie/src/main/java/com/airbnb/lottie/network/LottieNetworkResult.java similarity index 78% rename from lottie/src/main/java/com/airbnb/lottie/network/Result.java rename to lottie/src/main/java/com/airbnb/lottie/network/LottieNetworkResult.java index cf933731be..8294e542ea 100644 --- a/lottie/src/main/java/com/airbnb/lottie/network/Result.java +++ b/lottie/src/main/java/com/airbnb/lottie/network/LottieNetworkResult.java @@ -4,9 +4,9 @@ import androidx.annotation.NonNull; -public class Result { +public abstract class LottieNetworkResult { - public static class Success extends Result { + public static class Success extends LottieNetworkResult { @NonNull public final InputStream inputStream; @NonNull @@ -18,7 +18,7 @@ public Success(@NonNull InputStream inputStream, @NonNull String contentType) { } } - public static class Error extends Result { + public static class Error extends LottieNetworkResult { @NonNull public final String message; public final int responseCode; diff --git a/lottie/src/main/java/com/airbnb/lottie/network/NetworkCache.java b/lottie/src/main/java/com/airbnb/lottie/network/NetworkCache.java index feb370a977..41efc9f6b2 100644 --- a/lottie/src/main/java/com/airbnb/lottie/network/NetworkCache.java +++ b/lottie/src/main/java/com/airbnb/lottie/network/NetworkCache.java @@ -142,7 +142,7 @@ private File getCachedFile(String url) throws FileNotFoundException { } private File parentDir() { - File file= cacheDir.getCacheDir(); + File file = cacheDir.getCacheDir(); if (file.isFile()) { file.delete(); } diff --git a/lottie/src/main/java/com/airbnb/lottie/network/NetworkFetcher.java b/lottie/src/main/java/com/airbnb/lottie/network/NetworkFetcher.java index c7c1a06046..f466699578 100644 --- a/lottie/src/main/java/com/airbnb/lottie/network/NetworkFetcher.java +++ b/lottie/src/main/java/com/airbnb/lottie/network/NetworkFetcher.java @@ -73,16 +73,16 @@ private LottieResult fetchFromNetwork(@NonNull String url, @N Logger.debug("Fetching " + url); try { - Result fetchResult = fetcher.fetchSync(url); - if (fetchResult instanceof Result.Success) { - InputStream inputStream = ((Result.Success) fetchResult).inputStream; - String contentType = ((Result.Success) fetchResult).contentType; + LottieNetworkResult fetchResult = fetcher.fetchSync(url); + if (fetchResult instanceof LottieNetworkResult.Success) { + InputStream inputStream = ((LottieNetworkResult.Success) fetchResult).inputStream; + String contentType = ((LottieNetworkResult.Success) fetchResult).contentType; LottieResult result = fromInputStream(url, inputStream, contentType, cacheKey); Logger.debug("Completed fetch from network. Success: " + (result.getValue() != null)); return result; } else { - String error = ((Result.Error) fetchResult).message; - int responseCode = ((Result.Error) fetchResult).responseCode; + String error = ((LottieNetworkResult.Error) fetchResult).message; + int responseCode = ((LottieNetworkResult.Error) fetchResult).responseCode; return new LottieResult<>( new IllegalArgumentException("Unable to fetch " + url + ". Failed with " + responseCode + "\n" + error)); } From b452427ca66ae2a9fa4d20c1bdcc94892bd3013a Mon Sep 17 00:00:00 2001 From: Denis Egorov Date: Mon, 14 Sep 2020 23:25:20 +0300 Subject: [PATCH 07/17] fix --- lottie/src/main/java/com/airbnb/lottie/L.java | 18 ++++++++-------- .../java/com/airbnb/lottie/LottieConfig.java | 21 ++++++++++--------- ....java => DefaultLottieNetworkFetcher.java} | 2 +- ...r.java => LottieNetworkCacheProvider.java} | 4 ++-- ...Fetcher.java => LottieNetworkFetcher.java} | 2 +- .../airbnb/lottie/network/NetworkCache.java | 4 ++-- .../airbnb/lottie/network/NetworkFetcher.java | 4 ++-- 7 files changed, 28 insertions(+), 27 deletions(-) rename lottie/src/main/java/com/airbnb/lottie/network/{DefaultFetcher.java => DefaultLottieNetworkFetcher.java} (95%) rename lottie/src/main/java/com/airbnb/lottie/network/{CacheProvider.java => LottieNetworkCacheProvider.java} (59%) rename lottie/src/main/java/com/airbnb/lottie/network/{Fetcher.java => LottieNetworkFetcher.java} (87%) diff --git a/lottie/src/main/java/com/airbnb/lottie/L.java b/lottie/src/main/java/com/airbnb/lottie/L.java index eab00dde44..834b7e7a7b 100644 --- a/lottie/src/main/java/com/airbnb/lottie/L.java +++ b/lottie/src/main/java/com/airbnb/lottie/L.java @@ -2,9 +2,9 @@ import android.content.Context; -import com.airbnb.lottie.network.CacheProvider; -import com.airbnb.lottie.network.DefaultFetcher; -import com.airbnb.lottie.network.Fetcher; +import com.airbnb.lottie.network.LottieNetworkCacheProvider; +import com.airbnb.lottie.network.DefaultLottieNetworkFetcher; +import com.airbnb.lottie.network.LottieNetworkFetcher; import com.airbnb.lottie.network.NetworkCache; import com.airbnb.lottie.network.NetworkFetcher; @@ -27,8 +27,8 @@ public class L { private static int traceDepth = 0; private static int depthPastMaxDepth = 0; - private static Fetcher fetcher; - private static CacheProvider cacheProvider; + private static LottieNetworkFetcher fetcher; + private static LottieNetworkCacheProvider cacheProvider; private static volatile NetworkFetcher networkFetcher; private static volatile NetworkCache networkCache; @@ -78,11 +78,11 @@ public static float endSection(String section) { return (System.nanoTime() - startTimeNs[traceDepth]) / 1000000f; } - public static void setFetcher(Fetcher customFetcher) { + public static void setFetcher(LottieNetworkFetcher customFetcher) { fetcher = customFetcher; } - public static void setCacheProvider(CacheProvider customProvider) { + public static void setCacheProvider(LottieNetworkCacheProvider customProvider) { cacheProvider = customProvider; } @@ -93,7 +93,7 @@ public static NetworkFetcher networkFetcher(@NonNull Context context) { synchronized (NetworkFetcher.class) { local = networkFetcher; if (local == null) { - networkFetcher = local = new NetworkFetcher(networkCache(context), fetcher != null ? fetcher : new DefaultFetcher()); + networkFetcher = local = new NetworkFetcher(networkCache(context), fetcher != null ? fetcher : new DefaultLottieNetworkFetcher()); } } } @@ -107,7 +107,7 @@ public static NetworkCache networkCache(@NonNull final Context context) { synchronized (NetworkCache.class) { local = networkCache; if (local == null) { - networkCache = local = new NetworkCache(cacheProvider != null ? cacheProvider : new CacheProvider() { + networkCache = local = new NetworkCache(cacheProvider != null ? cacheProvider : new LottieNetworkCacheProvider() { @Override @NonNull public File getCacheDir() { return new File(context.getCacheDir(), "lottie_network_cache"); } diff --git a/lottie/src/main/java/com/airbnb/lottie/LottieConfig.java b/lottie/src/main/java/com/airbnb/lottie/LottieConfig.java index e9dc13e160..75a7c3f82e 100644 --- a/lottie/src/main/java/com/airbnb/lottie/LottieConfig.java +++ b/lottie/src/main/java/com/airbnb/lottie/LottieConfig.java @@ -2,8 +2,8 @@ import android.content.Context; -import com.airbnb.lottie.network.Fetcher; -import com.airbnb.lottie.network.CacheProvider; +import com.airbnb.lottie.network.LottieNetworkFetcher; +import com.airbnb.lottie.network.LottieNetworkCacheProvider; import java.io.File; @@ -16,10 +16,11 @@ public class LottieConfig { @NonNull final Context applicationContext; - @Nullable final Fetcher networkFetcher; - @Nullable final CacheProvider cacheProvider; + @Nullable final LottieNetworkFetcher networkFetcher; + @Nullable final LottieNetworkCacheProvider cacheProvider; - public LottieConfig(@NonNull Context applicationContext, @Nullable Fetcher networkFetcher, @Nullable CacheProvider cacheProvider) { + public LottieConfig(@NonNull Context applicationContext, @Nullable LottieNetworkFetcher networkFetcher, @Nullable + LottieNetworkCacheProvider cacheProvider) { this.applicationContext = applicationContext; this.networkFetcher = networkFetcher; this.cacheProvider = cacheProvider; @@ -30,23 +31,23 @@ public static final class Builder { @NonNull private final Context context; @Nullable - private Fetcher networkFetcher; + private LottieNetworkFetcher networkFetcher; @Nullable - private CacheProvider cacheProvider; + private LottieNetworkCacheProvider cacheProvider; public Builder(@NonNull Context context) { this.context = context.getApplicationContext(); } @NonNull - public Builder setNetworkFetcher(@NonNull Fetcher fetcher) { + public Builder setNetworkFetcher(@NonNull LottieNetworkFetcher fetcher) { this.networkFetcher = fetcher; return this; } @NonNull public Builder setCacheDir(@NonNull final File file) { - this.cacheProvider = new CacheProvider() { + this.cacheProvider = new LottieNetworkCacheProvider() { @Override @NonNull public File getCacheDir() { return file; } @@ -55,7 +56,7 @@ public Builder setCacheDir(@NonNull final File file) { } @NonNull - public Builder setCacheProvider(@NonNull CacheProvider fileCacheProvider) { + public Builder setCacheProvider(@NonNull LottieNetworkCacheProvider fileCacheProvider) { this.cacheProvider = fileCacheProvider; return this; } diff --git a/lottie/src/main/java/com/airbnb/lottie/network/DefaultFetcher.java b/lottie/src/main/java/com/airbnb/lottie/network/DefaultLottieNetworkFetcher.java similarity index 95% rename from lottie/src/main/java/com/airbnb/lottie/network/DefaultFetcher.java rename to lottie/src/main/java/com/airbnb/lottie/network/DefaultLottieNetworkFetcher.java index 3b10c52a37..bb6c4cad12 100644 --- a/lottie/src/main/java/com/airbnb/lottie/network/DefaultFetcher.java +++ b/lottie/src/main/java/com/airbnb/lottie/network/DefaultLottieNetworkFetcher.java @@ -8,7 +8,7 @@ import androidx.annotation.NonNull; -public class DefaultFetcher implements Fetcher { +public class DefaultLottieNetworkFetcher implements LottieNetworkFetcher { @Override @NonNull diff --git a/lottie/src/main/java/com/airbnb/lottie/network/CacheProvider.java b/lottie/src/main/java/com/airbnb/lottie/network/LottieNetworkCacheProvider.java similarity index 59% rename from lottie/src/main/java/com/airbnb/lottie/network/CacheProvider.java rename to lottie/src/main/java/com/airbnb/lottie/network/LottieNetworkCacheProvider.java index c55fe8bae5..2b01c67f0e 100644 --- a/lottie/src/main/java/com/airbnb/lottie/network/CacheProvider.java +++ b/lottie/src/main/java/com/airbnb/lottie/network/LottieNetworkCacheProvider.java @@ -5,9 +5,9 @@ import androidx.annotation.NonNull; /** - * Interface for providing the custom cache directory + * Interface for providing the custom cache directory where animations downloaded via url are saved */ -public interface CacheProvider { +public interface LottieNetworkCacheProvider { /** * Called during cache operations diff --git a/lottie/src/main/java/com/airbnb/lottie/network/Fetcher.java b/lottie/src/main/java/com/airbnb/lottie/network/LottieNetworkFetcher.java similarity index 87% rename from lottie/src/main/java/com/airbnb/lottie/network/Fetcher.java rename to lottie/src/main/java/com/airbnb/lottie/network/LottieNetworkFetcher.java index bbbb2e5dcc..d1e98c79b2 100644 --- a/lottie/src/main/java/com/airbnb/lottie/network/Fetcher.java +++ b/lottie/src/main/java/com/airbnb/lottie/network/LottieNetworkFetcher.java @@ -8,7 +8,7 @@ /** * Interface for custom fetcher */ -public interface Fetcher { +public interface LottieNetworkFetcher { @WorkerThread @NonNull LottieNetworkResult fetchSync(@NonNull String url) throws IOException; diff --git a/lottie/src/main/java/com/airbnb/lottie/network/NetworkCache.java b/lottie/src/main/java/com/airbnb/lottie/network/NetworkCache.java index 41efc9f6b2..3a4b59419c 100644 --- a/lottie/src/main/java/com/airbnb/lottie/network/NetworkCache.java +++ b/lottie/src/main/java/com/airbnb/lottie/network/NetworkCache.java @@ -22,9 +22,9 @@ public class NetworkCache { @NonNull - private final CacheProvider cacheDir; + private final LottieNetworkCacheProvider cacheDir; - public NetworkCache(@NonNull CacheProvider cacheDir) { + public NetworkCache(@NonNull LottieNetworkCacheProvider cacheDir) { this.cacheDir = cacheDir; } diff --git a/lottie/src/main/java/com/airbnb/lottie/network/NetworkFetcher.java b/lottie/src/main/java/com/airbnb/lottie/network/NetworkFetcher.java index f466699578..7c791e969a 100644 --- a/lottie/src/main/java/com/airbnb/lottie/network/NetworkFetcher.java +++ b/lottie/src/main/java/com/airbnb/lottie/network/NetworkFetcher.java @@ -22,9 +22,9 @@ public class NetworkFetcher { @NonNull private final NetworkCache networkCache; @NonNull - private final Fetcher fetcher; + private final LottieNetworkFetcher fetcher; - public NetworkFetcher(@NonNull NetworkCache networkCache, @NonNull Fetcher fetcher) { + public NetworkFetcher(@NonNull NetworkCache networkCache, @NonNull LottieNetworkFetcher fetcher) { this.networkCache = networkCache; this.fetcher = fetcher; } From d3dc4807e5ed071782a0dcd599b0d7435ecf8412 Mon Sep 17 00:00:00 2001 From: Denis Egorov Date: Tue, 15 Sep 2020 00:37:38 +0300 Subject: [PATCH 08/17] fix SocketTimeoutException --- .../network/DefaultLottieNetworkFetcher.java | 26 ++++++++++++------- .../lottie/network/LottieNetworkFetcher.java | 2 ++ .../airbnb/lottie/network/NetworkFetcher.java | 2 ++ 3 files changed, 20 insertions(+), 10 deletions(-) diff --git a/lottie/src/main/java/com/airbnb/lottie/network/DefaultLottieNetworkFetcher.java b/lottie/src/main/java/com/airbnb/lottie/network/DefaultLottieNetworkFetcher.java index bb6c4cad12..bef0f53430 100644 --- a/lottie/src/main/java/com/airbnb/lottie/network/DefaultLottieNetworkFetcher.java +++ b/lottie/src/main/java/com/airbnb/lottie/network/DefaultLottieNetworkFetcher.java @@ -7,26 +7,32 @@ import java.net.URL; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; public class DefaultLottieNetworkFetcher implements LottieNetworkFetcher { + @Nullable + private HttpURLConnection connection; + @Override @NonNull public LottieNetworkResult fetchSync(@NonNull String url) throws IOException { - HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection(); + connection = (HttpURLConnection) new URL(url).openConnection(); connection.setRequestMethod("GET"); - try { - connection.connect(); + connection.connect(); - if (connection.getErrorStream() != null || connection.getResponseCode() != HttpURLConnection.HTTP_OK) { - String error = getErrorFromConnection(connection); - return new LottieNetworkResult.Error("Unable to fetch " + url + ". Failed with " + connection.getResponseCode() + "\n" + error, - connection.getResponseCode()); - } + if (connection.getErrorStream() != null || connection.getResponseCode() != HttpURLConnection.HTTP_OK) { + String error = getErrorFromConnection(connection); + return new LottieNetworkResult.Error("Unable to fetch " + url + ". Failed with " + connection.getResponseCode() + "\n" + error, + connection.getResponseCode()); + } - return new LottieNetworkResult.Success(connection.getInputStream(), connection.getContentType()); - } finally { + return new LottieNetworkResult.Success(connection.getInputStream(), connection.getContentType()); + } + + @Override public void disconnect() { + if (connection != null) { connection.disconnect(); } } diff --git a/lottie/src/main/java/com/airbnb/lottie/network/LottieNetworkFetcher.java b/lottie/src/main/java/com/airbnb/lottie/network/LottieNetworkFetcher.java index d1e98c79b2..1e4f81797d 100644 --- a/lottie/src/main/java/com/airbnb/lottie/network/LottieNetworkFetcher.java +++ b/lottie/src/main/java/com/airbnb/lottie/network/LottieNetworkFetcher.java @@ -12,4 +12,6 @@ public interface LottieNetworkFetcher { @WorkerThread @NonNull LottieNetworkResult fetchSync(@NonNull String url) throws IOException; + + void disconnect(); } diff --git a/lottie/src/main/java/com/airbnb/lottie/network/NetworkFetcher.java b/lottie/src/main/java/com/airbnb/lottie/network/NetworkFetcher.java index 7c791e969a..4ed58ea9fa 100644 --- a/lottie/src/main/java/com/airbnb/lottie/network/NetworkFetcher.java +++ b/lottie/src/main/java/com/airbnb/lottie/network/NetworkFetcher.java @@ -88,6 +88,8 @@ private LottieResult fetchFromNetwork(@NonNull String url, @N } } catch (Exception e) { return new LottieResult<>(e); + } finally { + fetcher.disconnect(); } } From 2b3071514c18f65414e62168649175aacd0377af Mon Sep 17 00:00:00 2001 From: Denis Egorov Date: Wed, 16 Sep 2020 11:44:54 +0300 Subject: [PATCH 09/17] javadoc --- .../lottie/network/LottieNetworkCacheProvider.java | 4 +++- .../airbnb/lottie/network/LottieNetworkFetcher.java | 10 +++++++++- .../java/com/airbnb/lottie/network/NetworkCache.java | 8 ++++---- 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/lottie/src/main/java/com/airbnb/lottie/network/LottieNetworkCacheProvider.java b/lottie/src/main/java/com/airbnb/lottie/network/LottieNetworkCacheProvider.java index 2b01c67f0e..8258ba61c1 100644 --- a/lottie/src/main/java/com/airbnb/lottie/network/LottieNetworkCacheProvider.java +++ b/lottie/src/main/java/com/airbnb/lottie/network/LottieNetworkCacheProvider.java @@ -1,11 +1,13 @@ package com.airbnb.lottie.network; + import java.io.File; import androidx.annotation.NonNull; /** - * Interface for providing the custom cache directory where animations downloaded via url are saved + * Interface for providing the custom cache directory where animations downloaded via url are saved. + * @see com.airbnb.lottie.Lottie#initialize */ public interface LottieNetworkCacheProvider { diff --git a/lottie/src/main/java/com/airbnb/lottie/network/LottieNetworkFetcher.java b/lottie/src/main/java/com/airbnb/lottie/network/LottieNetworkFetcher.java index 1e4f81797d..438c685384 100644 --- a/lottie/src/main/java/com/airbnb/lottie/network/LottieNetworkFetcher.java +++ b/lottie/src/main/java/com/airbnb/lottie/network/LottieNetworkFetcher.java @@ -6,12 +6,20 @@ import androidx.annotation.WorkerThread; /** - * Interface for custom fetcher + * Implement this interface to handle network fetching manually when animations are requested via url. By default, Lottie will use an + * HttpUrlConnection under the hood but this enables you to hook into your own network stack. By default, Lottie will also handle caching the + * animations but if you want to provide your own cache directory, you may implement `LottieNetworkCacheProvider`. + * + * @see com.airbnb.lottie.Lottie#initialize */ public interface LottieNetworkFetcher { @WorkerThread @NonNull LottieNetworkResult fetchSync(@NonNull String url) throws IOException; + /** + * The method will be called after the animation has loaded. + * You can close your connection here. + */ void disconnect(); } diff --git a/lottie/src/main/java/com/airbnb/lottie/network/NetworkCache.java b/lottie/src/main/java/com/airbnb/lottie/network/NetworkCache.java index 3a4b59419c..71af6a898d 100644 --- a/lottie/src/main/java/com/airbnb/lottie/network/NetworkCache.java +++ b/lottie/src/main/java/com/airbnb/lottie/network/NetworkCache.java @@ -22,10 +22,10 @@ public class NetworkCache { @NonNull - private final LottieNetworkCacheProvider cacheDir; + private final LottieNetworkCacheProvider cacheProvider; - public NetworkCache(@NonNull LottieNetworkCacheProvider cacheDir) { - this.cacheDir = cacheDir; + public NetworkCache(@NonNull LottieNetworkCacheProvider cacheProvider) { + this.cacheProvider = cacheProvider; } public void clear() { @@ -142,7 +142,7 @@ private File getCachedFile(String url) throws FileNotFoundException { } private File parentDir() { - File file = cacheDir.getCacheDir(); + File file = cacheProvider.getCacheDir(); if (file.isFile()) { file.delete(); } From edb096b20c2af1d9816822728dc75ebeb6902ce5 Mon Sep 17 00:00:00 2001 From: Denis Egorov Date: Sun, 20 Sep 2020 14:12:51 +0300 Subject: [PATCH 10/17] private constructor --- lottie/src/main/java/com/airbnb/lottie/LottieConfig.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lottie/src/main/java/com/airbnb/lottie/LottieConfig.java b/lottie/src/main/java/com/airbnb/lottie/LottieConfig.java index 75a7c3f82e..e410d434d7 100644 --- a/lottie/src/main/java/com/airbnb/lottie/LottieConfig.java +++ b/lottie/src/main/java/com/airbnb/lottie/LottieConfig.java @@ -19,7 +19,7 @@ public class LottieConfig { @Nullable final LottieNetworkFetcher networkFetcher; @Nullable final LottieNetworkCacheProvider cacheProvider; - public LottieConfig(@NonNull Context applicationContext, @Nullable LottieNetworkFetcher networkFetcher, @Nullable + private LottieConfig(@NonNull Context applicationContext, @Nullable LottieNetworkFetcher networkFetcher, @Nullable LottieNetworkCacheProvider cacheProvider) { this.applicationContext = applicationContext; this.networkFetcher = networkFetcher; From c77366d7dffa6a4b9041618fa31c297a87502d99 Mon Sep 17 00:00:00 2001 From: Denis Egorov Date: Sun, 20 Sep 2020 14:42:42 +0300 Subject: [PATCH 11/17] delete context --- .../main/java/com/airbnb/lottie/LottieConfig.java | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/lottie/src/main/java/com/airbnb/lottie/LottieConfig.java b/lottie/src/main/java/com/airbnb/lottie/LottieConfig.java index e410d434d7..e4242c931f 100644 --- a/lottie/src/main/java/com/airbnb/lottie/LottieConfig.java +++ b/lottie/src/main/java/com/airbnb/lottie/LottieConfig.java @@ -1,7 +1,5 @@ package com.airbnb.lottie; -import android.content.Context; - import com.airbnb.lottie.network.LottieNetworkFetcher; import com.airbnb.lottie.network.LottieNetworkCacheProvider; @@ -15,30 +13,21 @@ */ public class LottieConfig { - @NonNull final Context applicationContext; @Nullable final LottieNetworkFetcher networkFetcher; @Nullable final LottieNetworkCacheProvider cacheProvider; - private LottieConfig(@NonNull Context applicationContext, @Nullable LottieNetworkFetcher networkFetcher, @Nullable - LottieNetworkCacheProvider cacheProvider) { - this.applicationContext = applicationContext; + private LottieConfig(@Nullable LottieNetworkFetcher networkFetcher, @Nullable LottieNetworkCacheProvider cacheProvider) { this.networkFetcher = networkFetcher; this.cacheProvider = cacheProvider; } public static final class Builder { - @NonNull - private final Context context; @Nullable private LottieNetworkFetcher networkFetcher; @Nullable private LottieNetworkCacheProvider cacheProvider; - public Builder(@NonNull Context context) { - this.context = context.getApplicationContext(); - } - @NonNull public Builder setNetworkFetcher(@NonNull LottieNetworkFetcher fetcher) { this.networkFetcher = fetcher; @@ -63,7 +52,7 @@ public Builder setCacheProvider(@NonNull LottieNetworkCacheProvider fileCachePro @NonNull public LottieConfig build() { - return new LottieConfig(context, networkFetcher, cacheProvider); + return new LottieConfig(networkFetcher, cacheProvider); } } } \ No newline at end of file From a76fe2bae88830f57ebb9b6e9e377859f99a49c0 Mon Sep 17 00:00:00 2001 From: Denis Egorov Date: Tue, 29 Sep 2020 20:57:11 +0300 Subject: [PATCH 12/17] fix problems with connections --- .../network/DefaultLottieNetworkFetcher.java | 16 +++++++++++----- .../lottie/network/LottieNetworkFetcher.java | 2 +- .../com/airbnb/lottie/network/NetworkCache.java | 3 ++- .../airbnb/lottie/network/NetworkFetcher.java | 5 +++-- 4 files changed, 17 insertions(+), 9 deletions(-) diff --git a/lottie/src/main/java/com/airbnb/lottie/network/DefaultLottieNetworkFetcher.java b/lottie/src/main/java/com/airbnb/lottie/network/DefaultLottieNetworkFetcher.java index bef0f53430..aba17eeb62 100644 --- a/lottie/src/main/java/com/airbnb/lottie/network/DefaultLottieNetworkFetcher.java +++ b/lottie/src/main/java/com/airbnb/lottie/network/DefaultLottieNetworkFetcher.java @@ -5,22 +5,24 @@ import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.URL; +import java.util.HashMap; +import java.util.Map; import androidx.annotation.NonNull; -import androidx.annotation.Nullable; public class DefaultLottieNetworkFetcher implements LottieNetworkFetcher { - @Nullable - private HttpURLConnection connection; + @NonNull + private final Map connections = new HashMap<>(); @Override @NonNull public LottieNetworkResult fetchSync(@NonNull String url) throws IOException { - connection = (HttpURLConnection) new URL(url).openConnection(); + HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection(); connection.setRequestMethod("GET"); connection.connect(); + connections.put(url, connection); if (connection.getErrorStream() != null || connection.getResponseCode() != HttpURLConnection.HTTP_OK) { String error = getErrorFromConnection(connection); @@ -31,7 +33,11 @@ public LottieNetworkResult fetchSync(@NonNull String url) throws IOException { return new LottieNetworkResult.Success(connection.getInputStream(), connection.getContentType()); } - @Override public void disconnect() { + @Override public void disconnect(@NonNull String url) { + if (!connections.containsKey(url)) { + return; + } + HttpURLConnection connection = connections.get(url); if (connection != null) { connection.disconnect(); } diff --git a/lottie/src/main/java/com/airbnb/lottie/network/LottieNetworkFetcher.java b/lottie/src/main/java/com/airbnb/lottie/network/LottieNetworkFetcher.java index 438c685384..0ec381ee1f 100644 --- a/lottie/src/main/java/com/airbnb/lottie/network/LottieNetworkFetcher.java +++ b/lottie/src/main/java/com/airbnb/lottie/network/LottieNetworkFetcher.java @@ -21,5 +21,5 @@ public interface LottieNetworkFetcher { * The method will be called after the animation has loaded. * You can close your connection here. */ - void disconnect(); + void disconnect(@NonNull String url); } diff --git a/lottie/src/main/java/com/airbnb/lottie/network/NetworkCache.java b/lottie/src/main/java/com/airbnb/lottie/network/NetworkCache.java index 71af6a898d..f0f29e132e 100644 --- a/lottie/src/main/java/com/airbnb/lottie/network/NetworkCache.java +++ b/lottie/src/main/java/com/airbnb/lottie/network/NetworkCache.java @@ -1,10 +1,11 @@ package com.airbnb.lottie.network; +import android.util.Pair; + import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.WorkerThread; -import androidx.core.util.Pair; import com.airbnb.lottie.utils.Logger; diff --git a/lottie/src/main/java/com/airbnb/lottie/network/NetworkFetcher.java b/lottie/src/main/java/com/airbnb/lottie/network/NetworkFetcher.java index 4ed58ea9fa..9aa854b6d0 100644 --- a/lottie/src/main/java/com/airbnb/lottie/network/NetworkFetcher.java +++ b/lottie/src/main/java/com/airbnb/lottie/network/NetworkFetcher.java @@ -1,5 +1,7 @@ package com.airbnb.lottie.network; +import android.util.Pair; + import com.airbnb.lottie.LottieComposition; import com.airbnb.lottie.LottieCompositionFactory; import com.airbnb.lottie.LottieResult; @@ -15,7 +17,6 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.WorkerThread; -import androidx.core.util.Pair; public class NetworkFetcher { @@ -89,7 +90,7 @@ private LottieResult fetchFromNetwork(@NonNull String url, @N } catch (Exception e) { return new LottieResult<>(e); } finally { - fetcher.disconnect(); + fetcher.disconnect(url); } } From f3a85686cc2430341829eda93902194a29a341f4 Mon Sep 17 00:00:00 2001 From: Denis Egorov Date: Tue, 29 Sep 2020 21:06:43 +0300 Subject: [PATCH 13/17] fix problems with connections --- .../com/airbnb/lottie/network/DefaultLottieNetworkFetcher.java | 1 + 1 file changed, 1 insertion(+) diff --git a/lottie/src/main/java/com/airbnb/lottie/network/DefaultLottieNetworkFetcher.java b/lottie/src/main/java/com/airbnb/lottie/network/DefaultLottieNetworkFetcher.java index aba17eeb62..3611f66c84 100644 --- a/lottie/src/main/java/com/airbnb/lottie/network/DefaultLottieNetworkFetcher.java +++ b/lottie/src/main/java/com/airbnb/lottie/network/DefaultLottieNetworkFetcher.java @@ -41,6 +41,7 @@ public LottieNetworkResult fetchSync(@NonNull String url) throws IOException { if (connection != null) { connection.disconnect(); } + connections.remove(url); } private String getErrorFromConnection(HttpURLConnection connection) throws IOException { From b70f6a72f9f8cf110432adb2a6ce0f0215a71a51 Mon Sep 17 00:00:00 2001 From: Denis Egorov Date: Thu, 1 Oct 2020 11:00:17 +0300 Subject: [PATCH 14/17] fix problems with connections --- .../network/DefaultLottieNetworkFetcher.java | 29 +++++----------- .../lottie/network/LottieNetworkFetcher.java | 6 ---- .../lottie/network/LottieNetworkResult.java | 33 +++++++++++++++++-- .../airbnb/lottie/network/NetworkFetcher.java | 7 ++-- 4 files changed, 44 insertions(+), 31 deletions(-) diff --git a/lottie/src/main/java/com/airbnb/lottie/network/DefaultLottieNetworkFetcher.java b/lottie/src/main/java/com/airbnb/lottie/network/DefaultLottieNetworkFetcher.java index 3611f66c84..3dda4f048a 100644 --- a/lottie/src/main/java/com/airbnb/lottie/network/DefaultLottieNetworkFetcher.java +++ b/lottie/src/main/java/com/airbnb/lottie/network/DefaultLottieNetworkFetcher.java @@ -1,47 +1,36 @@ package com.airbnb.lottie.network; import java.io.BufferedReader; +import java.io.Closeable; import java.io.IOException; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.URL; -import java.util.HashMap; -import java.util.Map; import androidx.annotation.NonNull; public class DefaultLottieNetworkFetcher implements LottieNetworkFetcher { - @NonNull - private final Map connections = new HashMap<>(); - @Override @NonNull public LottieNetworkResult fetchSync(@NonNull String url) throws IOException { - HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection(); + final HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection(); connection.setRequestMethod("GET"); connection.connect(); - connections.put(url, connection); + Closeable closeable = new Closeable() { + @Override public void close() { + connection.disconnect(); + } + }; if (connection.getErrorStream() != null || connection.getResponseCode() != HttpURLConnection.HTTP_OK) { String error = getErrorFromConnection(connection); return new LottieNetworkResult.Error("Unable to fetch " + url + ". Failed with " + connection.getResponseCode() + "\n" + error, - connection.getResponseCode()); + connection.getResponseCode(), closeable); } - return new LottieNetworkResult.Success(connection.getInputStream(), connection.getContentType()); - } - - @Override public void disconnect(@NonNull String url) { - if (!connections.containsKey(url)) { - return; - } - HttpURLConnection connection = connections.get(url); - if (connection != null) { - connection.disconnect(); - } - connections.remove(url); + return new LottieNetworkResult.Success(connection.getInputStream(), connection.getContentType(), closeable); } private String getErrorFromConnection(HttpURLConnection connection) throws IOException { diff --git a/lottie/src/main/java/com/airbnb/lottie/network/LottieNetworkFetcher.java b/lottie/src/main/java/com/airbnb/lottie/network/LottieNetworkFetcher.java index 0ec381ee1f..17edc9dbb1 100644 --- a/lottie/src/main/java/com/airbnb/lottie/network/LottieNetworkFetcher.java +++ b/lottie/src/main/java/com/airbnb/lottie/network/LottieNetworkFetcher.java @@ -16,10 +16,4 @@ public interface LottieNetworkFetcher { @WorkerThread @NonNull LottieNetworkResult fetchSync(@NonNull String url) throws IOException; - - /** - * The method will be called after the animation has loaded. - * You can close your connection here. - */ - void disconnect(@NonNull String url); } diff --git a/lottie/src/main/java/com/airbnb/lottie/network/LottieNetworkResult.java b/lottie/src/main/java/com/airbnb/lottie/network/LottieNetworkResult.java index 8294e542ea..16e3a8a219 100644 --- a/lottie/src/main/java/com/airbnb/lottie/network/LottieNetworkResult.java +++ b/lottie/src/main/java/com/airbnb/lottie/network/LottieNetworkResult.java @@ -1,10 +1,35 @@ package com.airbnb.lottie.network; +import com.airbnb.lottie.utils.Logger; + +import java.io.Closeable; import java.io.InputStream; import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +public abstract class LottieNetworkResult implements Closeable { -public abstract class LottieNetworkResult { + /** + * The closeable will be called after the animation has loaded. + * You can close your connection here. + */ + @Nullable + private final Closeable closeable; + + LottieNetworkResult(@Nullable Closeable closeable) { + this.closeable = closeable; + } + + @Override public void close() { + try { + if (closeable != null) { + closeable.close(); + } + } catch (Exception exception) { + Logger.error("LottieNetworkResult close: failed", exception); + } + } public static class Success extends LottieNetworkResult { @NonNull @@ -12,7 +37,8 @@ public static class Success extends LottieNetworkResult { @NonNull public final String contentType; - public Success(@NonNull InputStream inputStream, @NonNull String contentType) { + public Success(@NonNull InputStream inputStream, @NonNull String contentType, @Nullable Closeable closeable) { + super(closeable); this.inputStream = inputStream; this.contentType = contentType; } @@ -23,7 +49,8 @@ public static class Error extends LottieNetworkResult { public final String message; public final int responseCode; - public Error(@NonNull String message, int responseCode) { + public Error(@NonNull String message, int responseCode, @Nullable Closeable closeable) { + super(closeable); this.message = message; this.responseCode = responseCode; } diff --git a/lottie/src/main/java/com/airbnb/lottie/network/NetworkFetcher.java b/lottie/src/main/java/com/airbnb/lottie/network/NetworkFetcher.java index 9aa854b6d0..2a68981336 100644 --- a/lottie/src/main/java/com/airbnb/lottie/network/NetworkFetcher.java +++ b/lottie/src/main/java/com/airbnb/lottie/network/NetworkFetcher.java @@ -73,8 +73,9 @@ private LottieComposition fetchFromCache(@NonNull String url, @Nullable String c private LottieResult fetchFromNetwork(@NonNull String url, @Nullable String cacheKey) { Logger.debug("Fetching " + url); + LottieNetworkResult fetchResult = null; try { - LottieNetworkResult fetchResult = fetcher.fetchSync(url); + fetchResult = fetcher.fetchSync(url); if (fetchResult instanceof LottieNetworkResult.Success) { InputStream inputStream = ((LottieNetworkResult.Success) fetchResult).inputStream; String contentType = ((LottieNetworkResult.Success) fetchResult).contentType; @@ -90,7 +91,9 @@ private LottieResult fetchFromNetwork(@NonNull String url, @N } catch (Exception e) { return new LottieResult<>(e); } finally { - fetcher.disconnect(url); + if (fetchResult != null) { + fetchResult.close(); + } } } From d0d672373be8188dd63cd2ca98ae5cb3e9cae998 Mon Sep 17 00:00:00 2001 From: Denis Egorov Date: Thu, 1 Oct 2020 13:20:50 +0300 Subject: [PATCH 15/17] refactoring --- .../network/DefaultLottieFetchResult.java | 70 +++++++++++++++++++ .../network/DefaultLottieNetworkFetcher.java | 41 +---------- .../lottie/network/LottieFetchResult.java | 20 ++++++ .../lottie/network/LottieNetworkFetcher.java | 2 +- .../lottie/network/LottieNetworkResult.java | 58 --------------- .../airbnb/lottie/network/NetworkFetcher.java | 19 ++--- 6 files changed, 103 insertions(+), 107 deletions(-) create mode 100644 lottie/src/main/java/com/airbnb/lottie/network/DefaultLottieFetchResult.java create mode 100644 lottie/src/main/java/com/airbnb/lottie/network/LottieFetchResult.java delete mode 100644 lottie/src/main/java/com/airbnb/lottie/network/LottieNetworkResult.java diff --git a/lottie/src/main/java/com/airbnb/lottie/network/DefaultLottieFetchResult.java b/lottie/src/main/java/com/airbnb/lottie/network/DefaultLottieFetchResult.java new file mode 100644 index 0000000000..f9fc921c35 --- /dev/null +++ b/lottie/src/main/java/com/airbnb/lottie/network/DefaultLottieFetchResult.java @@ -0,0 +1,70 @@ +package com.airbnb.lottie.network; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.net.HttpURLConnection; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +public class DefaultLottieFetchResult implements LottieFetchResult { + + @NonNull + private final HttpURLConnection connection; + + public DefaultLottieFetchResult(@NonNull HttpURLConnection connection) { + this.connection = connection; + } + + @Override public boolean isSuccessful() throws IOException { + return resultCode() / 100 == 2; + } + + @Override public int resultCode() throws IOException { + return connection.getResponseCode(); + } + + @Nullable @Override public String message() throws IOException { + return connection.getResponseMessage(); + } + + @Nullable @Override public InputStream bodyByteStream() throws IOException { + return connection.getInputStream(); + } + + @Nullable @Override public String contentType() { + return connection.getContentType(); + } + + @Nullable @Override public String error() throws IOException { + return isSuccessful() ? null : + "Unable to fetch " + connection.getURL() + ". Failed with " + connection.getResponseCode() + "\n" + getErrorFromConnection(connection); + } + + @Override public void close() { + connection.disconnect(); + } + + private String getErrorFromConnection(HttpURLConnection connection) throws IOException { + BufferedReader r = new BufferedReader(new InputStreamReader(connection.getErrorStream())); + StringBuilder error = new StringBuilder(); + String line; + + try { + while ((line = r.readLine()) != null) { + error.append(line).append('\n'); + } + } catch (Exception e) { + throw e; + } finally { + try { + r.close(); + } catch (Exception e) { + // Do nothing. + } + } + return error.toString(); + } +} diff --git a/lottie/src/main/java/com/airbnb/lottie/network/DefaultLottieNetworkFetcher.java b/lottie/src/main/java/com/airbnb/lottie/network/DefaultLottieNetworkFetcher.java index 3dda4f048a..68b2ac9d16 100644 --- a/lottie/src/main/java/com/airbnb/lottie/network/DefaultLottieNetworkFetcher.java +++ b/lottie/src/main/java/com/airbnb/lottie/network/DefaultLottieNetworkFetcher.java @@ -1,9 +1,6 @@ package com.airbnb.lottie.network; -import java.io.BufferedReader; -import java.io.Closeable; import java.io.IOException; -import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.URL; @@ -13,44 +10,10 @@ public class DefaultLottieNetworkFetcher implements LottieNetworkFetcher { @Override @NonNull - public LottieNetworkResult fetchSync(@NonNull String url) throws IOException { + public LottieFetchResult fetchSync(@NonNull String url) throws IOException { final HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection(); connection.setRequestMethod("GET"); - connection.connect(); - Closeable closeable = new Closeable() { - @Override public void close() { - connection.disconnect(); - } - }; - - if (connection.getErrorStream() != null || connection.getResponseCode() != HttpURLConnection.HTTP_OK) { - String error = getErrorFromConnection(connection); - return new LottieNetworkResult.Error("Unable to fetch " + url + ". Failed with " + connection.getResponseCode() + "\n" + error, - connection.getResponseCode(), closeable); - } - - return new LottieNetworkResult.Success(connection.getInputStream(), connection.getContentType(), closeable); - } - - private String getErrorFromConnection(HttpURLConnection connection) throws IOException { - BufferedReader r = new BufferedReader(new InputStreamReader(connection.getErrorStream())); - StringBuilder error = new StringBuilder(); - String line; - - try { - while ((line = r.readLine()) != null) { - error.append(line).append('\n'); - } - } catch (Exception e) { - throw e; - } finally { - try { - r.close(); - } catch (Exception e) { - // Do nothing. - } - } - return error.toString(); + return new DefaultLottieFetchResult(connection); } } diff --git a/lottie/src/main/java/com/airbnb/lottie/network/LottieFetchResult.java b/lottie/src/main/java/com/airbnb/lottie/network/LottieFetchResult.java new file mode 100644 index 0000000000..05e5ab3ff9 --- /dev/null +++ b/lottie/src/main/java/com/airbnb/lottie/network/LottieFetchResult.java @@ -0,0 +1,20 @@ +package com.airbnb.lottie.network; + +import java.io.Closeable; +import java.io.IOException; +import java.io.InputStream; + +import androidx.annotation.Nullable; + +public interface LottieFetchResult extends Closeable { + boolean isSuccessful() throws IOException; + int resultCode() throws IOException; + @Nullable + String message() throws IOException; + @Nullable + InputStream bodyByteStream() throws IOException; + @Nullable + String contentType(); + @Nullable + String error() throws IOException; +} diff --git a/lottie/src/main/java/com/airbnb/lottie/network/LottieNetworkFetcher.java b/lottie/src/main/java/com/airbnb/lottie/network/LottieNetworkFetcher.java index 17edc9dbb1..48b7658221 100644 --- a/lottie/src/main/java/com/airbnb/lottie/network/LottieNetworkFetcher.java +++ b/lottie/src/main/java/com/airbnb/lottie/network/LottieNetworkFetcher.java @@ -15,5 +15,5 @@ public interface LottieNetworkFetcher { @WorkerThread @NonNull - LottieNetworkResult fetchSync(@NonNull String url) throws IOException; + LottieFetchResult fetchSync(@NonNull String url) throws IOException; } diff --git a/lottie/src/main/java/com/airbnb/lottie/network/LottieNetworkResult.java b/lottie/src/main/java/com/airbnb/lottie/network/LottieNetworkResult.java deleted file mode 100644 index 16e3a8a219..0000000000 --- a/lottie/src/main/java/com/airbnb/lottie/network/LottieNetworkResult.java +++ /dev/null @@ -1,58 +0,0 @@ -package com.airbnb.lottie.network; - -import com.airbnb.lottie.utils.Logger; - -import java.io.Closeable; -import java.io.InputStream; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; - -public abstract class LottieNetworkResult implements Closeable { - - /** - * The closeable will be called after the animation has loaded. - * You can close your connection here. - */ - @Nullable - private final Closeable closeable; - - LottieNetworkResult(@Nullable Closeable closeable) { - this.closeable = closeable; - } - - @Override public void close() { - try { - if (closeable != null) { - closeable.close(); - } - } catch (Exception exception) { - Logger.error("LottieNetworkResult close: failed", exception); - } - } - - public static class Success extends LottieNetworkResult { - @NonNull - public final InputStream inputStream; - @NonNull - public final String contentType; - - public Success(@NonNull InputStream inputStream, @NonNull String contentType, @Nullable Closeable closeable) { - super(closeable); - this.inputStream = inputStream; - this.contentType = contentType; - } - } - - public static class Error extends LottieNetworkResult { - @NonNull - public final String message; - public final int responseCode; - - public Error(@NonNull String message, int responseCode, @Nullable Closeable closeable) { - super(closeable); - this.message = message; - this.responseCode = responseCode; - } - } -} diff --git a/lottie/src/main/java/com/airbnb/lottie/network/NetworkFetcher.java b/lottie/src/main/java/com/airbnb/lottie/network/NetworkFetcher.java index 2a68981336..074ca98806 100644 --- a/lottie/src/main/java/com/airbnb/lottie/network/NetworkFetcher.java +++ b/lottie/src/main/java/com/airbnb/lottie/network/NetworkFetcher.java @@ -73,26 +73,27 @@ private LottieComposition fetchFromCache(@NonNull String url, @Nullable String c private LottieResult fetchFromNetwork(@NonNull String url, @Nullable String cacheKey) { Logger.debug("Fetching " + url); - LottieNetworkResult fetchResult = null; + LottieFetchResult fetchResult = null; try { fetchResult = fetcher.fetchSync(url); - if (fetchResult instanceof LottieNetworkResult.Success) { - InputStream inputStream = ((LottieNetworkResult.Success) fetchResult).inputStream; - String contentType = ((LottieNetworkResult.Success) fetchResult).contentType; + if (fetchResult.isSuccessful()) { + InputStream inputStream = fetchResult.bodyByteStream(); + String contentType = fetchResult.contentType(); LottieResult result = fromInputStream(url, inputStream, contentType, cacheKey); Logger.debug("Completed fetch from network. Success: " + (result.getValue() != null)); return result; } else { - String error = ((LottieNetworkResult.Error) fetchResult).message; - int responseCode = ((LottieNetworkResult.Error) fetchResult).responseCode; - return new LottieResult<>( - new IllegalArgumentException("Unable to fetch " + url + ". Failed with " + responseCode + "\n" + error)); + return new LottieResult<>(new IllegalArgumentException(fetchResult.error())); } } catch (Exception e) { return new LottieResult<>(e); } finally { if (fetchResult != null) { - fetchResult.close(); + try { + fetchResult.close(); + } catch (IOException e) { + e.printStackTrace(); + } } } } From 8a45420e8a27dc34c8e717d78bd562c7d2c35107 Mon Sep 17 00:00:00 2001 From: Denis Egorov Date: Mon, 5 Oct 2020 13:05:28 +0300 Subject: [PATCH 16/17] refactoring --- .../network/DefaultLottieFetchResult.java | 12 ++++---- .../lottie/network/LottieFetchResult.java | 30 +++++++++++++++++-- 2 files changed, 33 insertions(+), 9 deletions(-) diff --git a/lottie/src/main/java/com/airbnb/lottie/network/DefaultLottieFetchResult.java b/lottie/src/main/java/com/airbnb/lottie/network/DefaultLottieFetchResult.java index f9fc921c35..070a05d114 100644 --- a/lottie/src/main/java/com/airbnb/lottie/network/DefaultLottieFetchResult.java +++ b/lottie/src/main/java/com/airbnb/lottie/network/DefaultLottieFetchResult.java @@ -18,18 +18,18 @@ public DefaultLottieFetchResult(@NonNull HttpURLConnection connection) { this.connection = connection; } - @Override public boolean isSuccessful() throws IOException { - return resultCode() / 100 == 2; + @Override public boolean isSuccessful() { + try { + return resultCode() / 100 == 2; + } catch (IOException e) { + return false; + } } @Override public int resultCode() throws IOException { return connection.getResponseCode(); } - @Nullable @Override public String message() throws IOException { - return connection.getResponseMessage(); - } - @Nullable @Override public InputStream bodyByteStream() throws IOException { return connection.getInputStream(); } diff --git a/lottie/src/main/java/com/airbnb/lottie/network/LottieFetchResult.java b/lottie/src/main/java/com/airbnb/lottie/network/LottieFetchResult.java index 05e5ab3ff9..cb75336f6a 100644 --- a/lottie/src/main/java/com/airbnb/lottie/network/LottieFetchResult.java +++ b/lottie/src/main/java/com/airbnb/lottie/network/LottieFetchResult.java @@ -6,15 +6,39 @@ import androidx.annotation.Nullable; +/** + * The result of the operation of obtaining a lotty animation + */ public interface LottieFetchResult extends Closeable { - boolean isSuccessful() throws IOException; + /** + * @return Is the operation successful + */ + boolean isSuccessful(); + + /** + * + * @return Operation result code + */ int resultCode() throws IOException; - @Nullable - String message() throws IOException; + + /** + * + * @return Received content stream + */ @Nullable InputStream bodyByteStream() throws IOException; + + /** + * + * @return Type of content received + */ @Nullable String contentType(); + + /** + * + * @return Operation error + */ @Nullable String error() throws IOException; } From 099a2758e9656bbc11f7012bb9d07bf247a37cbb Mon Sep 17 00:00:00 2001 From: Denis Egorov Date: Mon, 19 Oct 2020 12:13:01 +0300 Subject: [PATCH 17/17] refactoring --- .../java/com/airbnb/lottie/LottieConfig.java | 17 ++++++++++++--- .../network/DefaultLottieFetchResult.java | 21 +++++++++++-------- .../lottie/network/LottieFetchResult.java | 13 ++++-------- .../airbnb/lottie/network/NetworkFetcher.java | 2 +- 4 files changed, 31 insertions(+), 22 deletions(-) diff --git a/lottie/src/main/java/com/airbnb/lottie/LottieConfig.java b/lottie/src/main/java/com/airbnb/lottie/LottieConfig.java index e4242c931f..2a560dcdf5 100644 --- a/lottie/src/main/java/com/airbnb/lottie/LottieConfig.java +++ b/lottie/src/main/java/com/airbnb/lottie/LottieConfig.java @@ -36,8 +36,11 @@ public Builder setNetworkFetcher(@NonNull LottieNetworkFetcher fetcher) { @NonNull public Builder setCacheDir(@NonNull final File file) { - this.cacheProvider = new LottieNetworkCacheProvider() { + cacheProvider = new LottieNetworkCacheProvider() { @Override @NonNull public File getCacheDir() { + if (!file.isDirectory()) { + throw new IllegalArgumentException("cache file must be a directory"); + } return file; } }; @@ -45,8 +48,16 @@ public Builder setCacheDir(@NonNull final File file) { } @NonNull - public Builder setCacheProvider(@NonNull LottieNetworkCacheProvider fileCacheProvider) { - this.cacheProvider = fileCacheProvider; + public Builder setCacheProvider(@NonNull final LottieNetworkCacheProvider fileCacheProvider) { + cacheProvider = new LottieNetworkCacheProvider() { + @NonNull @Override public File getCacheDir() { + File file = fileCacheProvider.getCacheDir(); + if (!file.isDirectory()) { + throw new IllegalArgumentException("cache file must be a directory"); + } + return file; + } + }; return this; } diff --git a/lottie/src/main/java/com/airbnb/lottie/network/DefaultLottieFetchResult.java b/lottie/src/main/java/com/airbnb/lottie/network/DefaultLottieFetchResult.java index 070a05d114..9a408efe3b 100644 --- a/lottie/src/main/java/com/airbnb/lottie/network/DefaultLottieFetchResult.java +++ b/lottie/src/main/java/com/airbnb/lottie/network/DefaultLottieFetchResult.java @@ -1,5 +1,7 @@ package com.airbnb.lottie.network; +import com.airbnb.lottie.utils.Logger; + import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; @@ -20,17 +22,13 @@ public DefaultLottieFetchResult(@NonNull HttpURLConnection connection) { @Override public boolean isSuccessful() { try { - return resultCode() / 100 == 2; + return connection.getResponseCode() / 100 == 2; } catch (IOException e) { return false; } } - @Override public int resultCode() throws IOException { - return connection.getResponseCode(); - } - - @Nullable @Override public InputStream bodyByteStream() throws IOException { + @NonNull @Override public InputStream bodyByteStream() throws IOException { return connection.getInputStream(); } @@ -38,9 +36,14 @@ public DefaultLottieFetchResult(@NonNull HttpURLConnection connection) { return connection.getContentType(); } - @Nullable @Override public String error() throws IOException { - return isSuccessful() ? null : - "Unable to fetch " + connection.getURL() + ". Failed with " + connection.getResponseCode() + "\n" + getErrorFromConnection(connection); + @Nullable @Override public String error() { + try { + return isSuccessful() ? null : + "Unable to fetch " + connection.getURL() + ". Failed with " + connection.getResponseCode() + "\n" + getErrorFromConnection(connection); + } catch (IOException e) { + Logger.warning("get error failed ", e); + return e.getMessage(); + } } @Override public void close() { diff --git a/lottie/src/main/java/com/airbnb/lottie/network/LottieFetchResult.java b/lottie/src/main/java/com/airbnb/lottie/network/LottieFetchResult.java index cb75336f6a..5a1a762125 100644 --- a/lottie/src/main/java/com/airbnb/lottie/network/LottieFetchResult.java +++ b/lottie/src/main/java/com/airbnb/lottie/network/LottieFetchResult.java @@ -4,10 +4,11 @@ import java.io.IOException; import java.io.InputStream; +import androidx.annotation.NonNull; import androidx.annotation.Nullable; /** - * The result of the operation of obtaining a lotty animation + * The result of the operation of obtaining a Lottie animation */ public interface LottieFetchResult extends Closeable { /** @@ -15,17 +16,11 @@ public interface LottieFetchResult extends Closeable { */ boolean isSuccessful(); - /** - * - * @return Operation result code - */ - int resultCode() throws IOException; - /** * * @return Received content stream */ - @Nullable + @NonNull InputStream bodyByteStream() throws IOException; /** @@ -40,5 +35,5 @@ public interface LottieFetchResult extends Closeable { * @return Operation error */ @Nullable - String error() throws IOException; + String error(); } diff --git a/lottie/src/main/java/com/airbnb/lottie/network/NetworkFetcher.java b/lottie/src/main/java/com/airbnb/lottie/network/NetworkFetcher.java index 074ca98806..21fbc3400e 100644 --- a/lottie/src/main/java/com/airbnb/lottie/network/NetworkFetcher.java +++ b/lottie/src/main/java/com/airbnb/lottie/network/NetworkFetcher.java @@ -92,7 +92,7 @@ private LottieResult fetchFromNetwork(@NonNull String url, @N try { fetchResult.close(); } catch (IOException e) { - e.printStackTrace(); + Logger.warning("LottieFetchResult close failed ", e); } } }