image-loader add scheme handling abstraction
This commit is contained in:
parent
836cef28ed
commit
fde9712454
@ -7,13 +7,7 @@ import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.lang.ref.WeakReference;
|
||||
@ -23,13 +17,10 @@ import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
import okhttp3.Call;
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
import okhttp3.ResponseBody;
|
||||
import ru.noties.markwon.spans.AsyncDrawable;
|
||||
|
||||
public class AsyncDrawableLoader implements AsyncDrawable.Loader {
|
||||
@ -44,31 +35,19 @@ public class AsyncDrawableLoader implements AsyncDrawable.Loader {
|
||||
return new Builder();
|
||||
}
|
||||
|
||||
private static final String HEADER_CONTENT_TYPE = "Content-Type";
|
||||
|
||||
private static final String FILE_ANDROID_ASSETS = "android_asset";
|
||||
|
||||
private static final String SCHEME_FILE = "file";
|
||||
private static final String SCHEME_DATA = "data";
|
||||
|
||||
private static final DataUriParser DATA_URI_PARSER = DataUriParser.create();
|
||||
private static final DataUriDecoder DATA_URI_DECODER = DataUriDecoder.create();
|
||||
|
||||
private final OkHttpClient client;
|
||||
private final Resources resources;
|
||||
private final ExecutorService executorService;
|
||||
private final Handler mainThread;
|
||||
private final Drawable errorDrawable;
|
||||
private final Map<String, SchemeHandler> schemeHandlers;
|
||||
private final List<MediaDecoder> mediaDecoders;
|
||||
|
||||
private final Map<String, Future<?>> requests;
|
||||
|
||||
AsyncDrawableLoader(Builder builder) {
|
||||
this.client = builder.client;
|
||||
this.resources = builder.resources;
|
||||
this.executorService = builder.executorService;
|
||||
this.mainThread = new Handler(Looper.getMainLooper());
|
||||
this.errorDrawable = builder.errorDrawable;
|
||||
this.schemeHandlers = builder.schemeHandlers;
|
||||
this.mediaDecoders = builder.mediaDecoders;
|
||||
this.requests = new HashMap<>(3);
|
||||
}
|
||||
@ -88,61 +67,58 @@ public class AsyncDrawableLoader implements AsyncDrawable.Loader {
|
||||
request.cancel(true);
|
||||
}
|
||||
|
||||
final List<Call> calls = client.dispatcher().queuedCalls();
|
||||
if (calls != null) {
|
||||
for (Call call : calls) {
|
||||
if (!call.isCanceled()) {
|
||||
if (destination.equals(call.request().tag())) {
|
||||
call.cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
for (SchemeHandler schemeHandler : schemeHandlers.values()) {
|
||||
schemeHandler.cancel(destination);
|
||||
}
|
||||
}
|
||||
|
||||
private Future<?> execute(@NonNull final String destination, @NonNull AsyncDrawable drawable) {
|
||||
|
||||
final WeakReference<AsyncDrawable> reference = new WeakReference<AsyncDrawable>(drawable);
|
||||
|
||||
// todo: should we cancel pending request for the same destination?
|
||||
// we _could_ but there is possibility that one resource is request in multiple places
|
||||
|
||||
// todo, if not a link -> show placeholder
|
||||
|
||||
return executorService.submit(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
final Item item;
|
||||
final boolean isFromFile;
|
||||
final ImageItem item;
|
||||
|
||||
final Uri uri = Uri.parse(destination);
|
||||
final String scheme = uri.getScheme();
|
||||
|
||||
if (SCHEME_FILE.equals(scheme)) {
|
||||
item = fromFile(uri);
|
||||
isFromFile = true;
|
||||
} else if (SCHEME_DATA.equals(scheme)) {
|
||||
item = fromData(uri.getSchemeSpecificPart());
|
||||
isFromFile = false;
|
||||
final SchemeHandler schemeHandler = schemeHandlers.get(uri.getScheme());
|
||||
if (schemeHandler != null) {
|
||||
item = schemeHandler.handle(destination, uri);
|
||||
} else {
|
||||
item = fromNetwork(destination);
|
||||
isFromFile = false;
|
||||
item = null;
|
||||
}
|
||||
|
||||
final InputStream inputStream = item != null
|
||||
? item.inputStream()
|
||||
: null;
|
||||
|
||||
Drawable result = null;
|
||||
|
||||
if (item != null
|
||||
&& item.inputStream != null) {
|
||||
if (inputStream != null) {
|
||||
try {
|
||||
|
||||
final MediaDecoder mediaDecoder = isFromFile
|
||||
? mediaDecoderFromFile(item.fileName)
|
||||
: mediaDecoderFromContentType(item.contentType);
|
||||
final String fileName = item.fileName();
|
||||
final MediaDecoder mediaDecoder = fileName != null
|
||||
? mediaDecoderFromFile(fileName)
|
||||
: mediaDecoderFromContentType(item.contentType());
|
||||
|
||||
if (mediaDecoder != null) {
|
||||
result = mediaDecoder.decode(item.inputStream);
|
||||
result = mediaDecoder.decode(inputStream);
|
||||
}
|
||||
|
||||
} finally {
|
||||
try {
|
||||
item.inputStream.close();
|
||||
inputStream.close();
|
||||
} catch (IOException e) {
|
||||
// no op
|
||||
// ignored
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -170,112 +146,6 @@ public class AsyncDrawableLoader implements AsyncDrawable.Loader {
|
||||
});
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Item fromFile(@NonNull Uri uri) {
|
||||
|
||||
final List<String> segments = uri.getPathSegments();
|
||||
if (segments == null
|
||||
|| segments.size() == 0) {
|
||||
// pointing to file & having no path segments is no use
|
||||
return null;
|
||||
}
|
||||
|
||||
final Item out;
|
||||
final InputStream inputStream;
|
||||
|
||||
final boolean assets = FILE_ANDROID_ASSETS.equals(segments.get(0));
|
||||
final String fileName = uri.getLastPathSegment();
|
||||
|
||||
if (assets) {
|
||||
final StringBuilder path = new StringBuilder();
|
||||
for (int i = 1, size = segments.size(); i < size; i++) {
|
||||
if (i != 1) {
|
||||
path.append('/');
|
||||
}
|
||||
path.append(segments.get(i));
|
||||
}
|
||||
// load assets
|
||||
InputStream inner = null;
|
||||
try {
|
||||
inner = resources.getAssets().open(path.toString());
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
inputStream = inner;
|
||||
} else {
|
||||
InputStream inner = null;
|
||||
try {
|
||||
inner = new BufferedInputStream(new FileInputStream(new File(uri.getPath())));
|
||||
} catch (FileNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
inputStream = inner;
|
||||
}
|
||||
|
||||
if (inputStream != null) {
|
||||
out = new Item(fileName, null, inputStream);
|
||||
} else {
|
||||
out = null;
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Item fromData(@Nullable String part) {
|
||||
|
||||
if (TextUtils.isEmpty(part)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final DataUri dataUri = DATA_URI_PARSER.parse(part);
|
||||
if (dataUri == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final byte[] bytes = DATA_URI_DECODER.decode(dataUri);
|
||||
if (bytes == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new Item(
|
||||
null,
|
||||
dataUri.contentType(),
|
||||
new ByteArrayInputStream(bytes)
|
||||
);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Item fromNetwork(@NonNull String destination) {
|
||||
|
||||
Item out = null;
|
||||
|
||||
final Request request = new Request.Builder()
|
||||
.url(destination)
|
||||
.tag(destination)
|
||||
.build();
|
||||
|
||||
Response response = null;
|
||||
try {
|
||||
response = client.newCall(request).execute();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
if (response != null) {
|
||||
final ResponseBody body = response.body();
|
||||
if (body != null) {
|
||||
final InputStream inputStream = body.byteStream();
|
||||
if (inputStream != null) {
|
||||
final String contentType = response.header(HEADER_CONTENT_TYPE);
|
||||
out = new Item(null, contentType, inputStream);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private MediaDecoder mediaDecoderFromFile(@NonNull String fileName) {
|
||||
|
||||
@ -313,11 +183,15 @@ public class AsyncDrawableLoader implements AsyncDrawable.Loader {
|
||||
private ExecutorService executorService;
|
||||
private Drawable errorDrawable;
|
||||
|
||||
// @since 2.0.0
|
||||
private final Map<String, SchemeHandler> schemeHandlers = new HashMap<>(3);
|
||||
|
||||
// @since 1.1.0
|
||||
private final List<MediaDecoder> mediaDecoders = new ArrayList<>(3);
|
||||
|
||||
|
||||
@NonNull
|
||||
@Deprecated
|
||||
public Builder client(@NonNull OkHttpClient client) {
|
||||
this.client = client;
|
||||
return this;
|
||||
@ -347,6 +221,15 @@ public class AsyncDrawableLoader implements AsyncDrawable.Loader {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 2.0.0
|
||||
*/
|
||||
@NonNull
|
||||
public Builder schemeHandler(@NonNull String scheme, @Nullable SchemeHandler schemeHandler) {
|
||||
schemeHandlers.put(scheme, schemeHandler);
|
||||
return this;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public Builder mediaDecoders(@NonNull List<MediaDecoder> mediaDecoders) {
|
||||
this.mediaDecoders.clear();
|
||||
@ -367,17 +250,44 @@ public class AsyncDrawableLoader implements AsyncDrawable.Loader {
|
||||
@NonNull
|
||||
public AsyncDrawableLoader build() {
|
||||
|
||||
if (client == null) {
|
||||
client = new OkHttpClient();
|
||||
}
|
||||
|
||||
// I think we should deprecate this...
|
||||
if (resources == null) {
|
||||
resources = Resources.getSystem();
|
||||
}
|
||||
|
||||
if (executorService == null) {
|
||||
// we will use executor from okHttp
|
||||
executorService = client.dispatcher().executorService();
|
||||
executorService = Executors.newCachedThreadPool();
|
||||
}
|
||||
|
||||
// @since 2.0.0
|
||||
// put default scheme handlers (to mimic previous behavior)
|
||||
{
|
||||
|
||||
final boolean hasHttp = schemeHandlers.containsKey("http");
|
||||
final boolean hasHttps = schemeHandlers.containsKey("https");
|
||||
|
||||
if (!hasHttp || !hasHttps) {
|
||||
|
||||
if (client == null) {
|
||||
client = new OkHttpClient();
|
||||
}
|
||||
|
||||
final NetworkSchemeHandler handler = NetworkSchemeHandler.create(client);
|
||||
if (!hasHttp) {
|
||||
schemeHandlers.put("http", handler);
|
||||
}
|
||||
if (!hasHttps) {
|
||||
schemeHandlers.put("https", handler);
|
||||
}
|
||||
}
|
||||
|
||||
if (!schemeHandlers.containsKey("file")) {
|
||||
schemeHandlers.put("file", FileSchemeHandler.createWithAssets(resources.getAssets()));
|
||||
}
|
||||
|
||||
if (!schemeHandlers.containsKey("data")) {
|
||||
schemeHandlers.put("data", DataUriSchemeHandler.create());
|
||||
}
|
||||
}
|
||||
|
||||
// add default media decoders if not specified
|
||||
@ -390,17 +300,4 @@ public class AsyncDrawableLoader implements AsyncDrawable.Loader {
|
||||
return new AsyncDrawableLoader(this);
|
||||
}
|
||||
}
|
||||
|
||||
private static class Item {
|
||||
|
||||
final String fileName;
|
||||
final String contentType;
|
||||
final InputStream inputStream;
|
||||
|
||||
Item(@Nullable String fileName, @Nullable String contentType, @Nullable InputStream inputStream) {
|
||||
this.fileName = fileName;
|
||||
this.contentType = contentType;
|
||||
this.inputStream = inputStream;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,60 @@
|
||||
package ru.noties.markwon.il;
|
||||
|
||||
import android.net.Uri;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.text.TextUtils;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
|
||||
/**
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public class DataUriSchemeHandler extends SchemeHandler {
|
||||
|
||||
@NonNull
|
||||
public static DataUriSchemeHandler create() {
|
||||
return new DataUriSchemeHandler(DataUriParser.create(), DataUriDecoder.create());
|
||||
}
|
||||
|
||||
private final DataUriParser uriParser;
|
||||
private final DataUriDecoder uriDecoder;
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
DataUriSchemeHandler(@NonNull DataUriParser uriParser, @NonNull DataUriDecoder uriDecoder) {
|
||||
this.uriParser = uriParser;
|
||||
this.uriDecoder = uriDecoder;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public ImageItem handle(@NonNull String raw, @NonNull Uri uri) {
|
||||
|
||||
final String part = uri.getSchemeSpecificPart();
|
||||
|
||||
if (TextUtils.isEmpty(part)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final DataUri dataUri = uriParser.parse(part);
|
||||
if (dataUri == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final byte[] bytes = uriDecoder.decode(dataUri);
|
||||
if (bytes == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new ImageItem(
|
||||
dataUri.contentType(),
|
||||
new ByteArrayInputStream(bytes),
|
||||
null
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancel(@NonNull String raw) {
|
||||
// no op
|
||||
}
|
||||
}
|
@ -0,0 +1,101 @@
|
||||
package ru.noties.markwon.il;
|
||||
|
||||
import android.content.res.AssetManager;
|
||||
import android.net.Uri;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public class FileSchemeHandler extends SchemeHandler {
|
||||
|
||||
@NonNull
|
||||
public static FileSchemeHandler createWithAssets(@NonNull AssetManager assetManager) {
|
||||
return new FileSchemeHandler(assetManager);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public static FileSchemeHandler create() {
|
||||
return new FileSchemeHandler(null);
|
||||
}
|
||||
|
||||
private static final String FILE_ANDROID_ASSETS = "android_asset";
|
||||
|
||||
@Nullable
|
||||
private final AssetManager assetManager;
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
FileSchemeHandler(@Nullable AssetManager assetManager) {
|
||||
this.assetManager = assetManager;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public ImageItem handle(@NonNull String raw, @NonNull Uri uri) {
|
||||
|
||||
final List<String> segments = uri.getPathSegments();
|
||||
if (segments == null
|
||||
|| segments.size() == 0) {
|
||||
// pointing to file & having no path segments is no use
|
||||
return null;
|
||||
}
|
||||
|
||||
final ImageItem out;
|
||||
|
||||
InputStream inputStream = null;
|
||||
|
||||
final boolean assets = FILE_ANDROID_ASSETS.equals(segments.get(0));
|
||||
final String fileName = uri.getLastPathSegment();
|
||||
|
||||
if (assets) {
|
||||
|
||||
// no handling of assets here if we have no assetsManager
|
||||
if (assetManager != null) {
|
||||
|
||||
final StringBuilder path = new StringBuilder();
|
||||
for (int i = 1, size = segments.size(); i < size; i++) {
|
||||
if (i != 1) {
|
||||
path.append('/');
|
||||
}
|
||||
path.append(segments.get(i));
|
||||
}
|
||||
// load assets
|
||||
|
||||
try {
|
||||
inputStream = assetManager.open(path.toString());
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
try {
|
||||
inputStream = new BufferedInputStream(new FileInputStream(new File(uri.getPath())));
|
||||
} catch (FileNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (inputStream != null) {
|
||||
out = new ImageItem(fileName, inputStream, fileName);
|
||||
} else {
|
||||
out = null;
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancel(@NonNull String raw) {
|
||||
// no op
|
||||
}
|
||||
}
|
@ -13,6 +13,7 @@ import pl.droidsonroids.gif.GifDrawable;
|
||||
/**
|
||||
* @since 1.1.0
|
||||
*/
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
public class GifMediaDecoder extends MediaDecoder {
|
||||
|
||||
protected static final String CONTENT_TYPE_GIF = "image/gif";
|
||||
|
@ -0,0 +1,39 @@
|
||||
package ru.noties.markwon.il;
|
||||
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
import java.io.InputStream;
|
||||
|
||||
/**
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public class ImageItem {
|
||||
|
||||
private final String contentType;
|
||||
private final InputStream inputStream;
|
||||
private final String fileName;
|
||||
|
||||
public ImageItem(
|
||||
@Nullable String contentType,
|
||||
@Nullable InputStream inputStream,
|
||||
@Nullable String fileName) {
|
||||
this.contentType = contentType;
|
||||
this.inputStream = inputStream;
|
||||
this.fileName = fileName;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String contentType() {
|
||||
return contentType;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public InputStream inputStream() {
|
||||
return inputStream;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String fileName() {
|
||||
return fileName;
|
||||
}
|
||||
}
|
@ -25,6 +25,7 @@ public class ImageMediaDecoder extends MediaDecoder {
|
||||
|
||||
private final Resources resources;
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
ImageMediaDecoder(Resources resources) {
|
||||
this.resources = resources;
|
||||
}
|
||||
@ -45,6 +46,7 @@ public class ImageMediaDecoder extends MediaDecoder {
|
||||
|
||||
final Drawable out;
|
||||
|
||||
// absolutely not optimal... thing
|
||||
final Bitmap bitmap = BitmapFactory.decodeStream(inputStream);
|
||||
if (bitmap != null) {
|
||||
out = new BitmapDrawable(resources, bitmap);
|
||||
|
@ -0,0 +1,81 @@
|
||||
package ru.noties.markwon.il;
|
||||
|
||||
import android.net.Uri;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.List;
|
||||
|
||||
import okhttp3.Call;
|
||||
import okhttp3.OkHttpClient;
|
||||
import okhttp3.Request;
|
||||
import okhttp3.Response;
|
||||
import okhttp3.ResponseBody;
|
||||
|
||||
/**
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public class NetworkSchemeHandler extends SchemeHandler {
|
||||
|
||||
@NonNull
|
||||
public static NetworkSchemeHandler create(@NonNull OkHttpClient client) {
|
||||
return new NetworkSchemeHandler(client);
|
||||
}
|
||||
|
||||
private static final String HEADER_CONTENT_TYPE = "Content-Type";
|
||||
|
||||
private final OkHttpClient client;
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
NetworkSchemeHandler(@NonNull OkHttpClient client) {
|
||||
this.client = client;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public ImageItem handle(@NonNull String raw, @NonNull Uri uri) {
|
||||
|
||||
ImageItem out = null;
|
||||
|
||||
final Request request = new Request.Builder()
|
||||
.url(raw)
|
||||
.tag(raw)
|
||||
.build();
|
||||
|
||||
Response response = null;
|
||||
try {
|
||||
response = client.newCall(request).execute();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
if (response != null) {
|
||||
final ResponseBody body = response.body();
|
||||
if (body != null) {
|
||||
final InputStream inputStream = body.byteStream();
|
||||
if (inputStream != null) {
|
||||
final String contentType = response.header(HEADER_CONTENT_TYPE);
|
||||
out = new ImageItem(contentType, inputStream, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancel(@NonNull String raw) {
|
||||
final List<Call> calls = client.dispatcher().queuedCalls();
|
||||
if (calls != null) {
|
||||
for (Call call : calls) {
|
||||
if (!call.isCanceled()) {
|
||||
if (raw.equals(call.request().tag())) {
|
||||
call.cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
package ru.noties.markwon.il;
|
||||
|
||||
import android.net.Uri;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
/**
|
||||
* @since 2.0.0
|
||||
*/
|
||||
public abstract class SchemeHandler {
|
||||
|
||||
@Nullable
|
||||
public abstract ImageItem handle(@NonNull String raw, @NonNull Uri uri);
|
||||
|
||||
public abstract void cancel(@NonNull String raw);
|
||||
}
|
@ -28,6 +28,7 @@ public class SvgMediaDecoder extends MediaDecoder {
|
||||
|
||||
private final Resources resources;
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
SvgMediaDecoder(Resources resources) {
|
||||
this.resources = resources;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user