Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fallback for Url : to another Url #606

Closed
vsahu1986 opened this issue Sep 1, 2015 · 11 comments
Closed

Fallback for Url : to another Url #606

vsahu1986 opened this issue Sep 1, 2015 · 11 comments

Comments

@vsahu1986
Copy link

#454
#456
#451

Glide.with(getActivity()).load(Utils.getYoutubeUrl(density, getArguments().getString(VIDEO_ID))).asBitmap().error(R.drawable.ic_error_icon).into(glideImageView);

I wish I could get Exception listener for 404

like if particular url returns 404 then retry with fallback url instead of drawable .

Example Url1 - http://img.youtube.com/vi/watsQDZ3KNw/sddefault.jpg

if Url1 returns 404 then fallback

http://img.youtube.com/vi/watsQDZ3KNw/mddefault.jpg

I am using Youtube Image API , which does always have mddefault.jpg and higher version might not available .

@vipinhelloindia
Copy link

+1

@TWiStErRob
Copy link
Collaborator

I wish I could get Exception listener for 404

How about .listener() and it's onException method? You can inspect the exception (instanceof, getMessage().contains()) and figure out what to do. It's not convenient, but possible.

like if particular url returns 404 then retry with fallback url instead of drawable .

That's what #451 is there for, put a +1 on that.

@vsahu1986
Copy link
Author

Thanks @TWiStErRob , I will give it a try ,

I really concern about the convenient way for 404 status

@sjudd
Copy link
Collaborator

sjudd commented Sep 2, 2015

Looks like a duplicate of #451

@TWiStErRob
Copy link
Collaborator

This is an untested alternative solution:

Glide.with(context).load(new YouTubeVideo("watsQDZ3KNw")).into(imageView);

// TODO https://github.com/bumptech/glide/wiki/Configuration#creating-a-glidemodule
class YouTubeGlideModule implements GlideModule {
    @Override public void applyOptions(Context context, GlideBuilder builder) {
    }
    @Override public void registerComponents(Context context, Glide glide) {
        glide.register(YouTubeVideo.class, InputStream.class, new YTVModelLoader.Factory());
    }
}

class YouTubeVideo {
    String id;
    public YouTubeVideo(String id) {
        this.id = id;
    }
    public String getSDUrl() {
        return String.format(Locale.ROOT, "http://img.youtube.com/vi/%s/sddefault.jpg", id);
    }
    public String getMDUrl() {
        return String.format(Locale.ROOT, "http://img.youtube.com/vi/%s/mddefault.jpg", id);
    }
}

class YTVModelLoader implements StreamModelLoader<YouTubeVideo> {
    private final ModelLoader<String, InputStream> loader;
    public YTVModelLoader(ModelLoader<String, InputStream> loader) {
        this.loader = loader;
    }
    @Override public DataFetcher<InputStream> getResourceFetcher(final YouTubeVideo model, final int width,
            final int height) {
        return new DataFetcher<InputStream>() {
            private DataFetcher<InputStream> fetcher;

            @Override public String getId() {
                return model.id; // assuming that if SDUrl failed once, it'll fail the next time
                // so it's better to cache MDUrl in that case for this video, forever
            }

            @Override public InputStream loadData(Priority priority) throws Exception {
                try {
                    fetcher = loader.getResourceFetcher(model.getSDUrl(), width, height);
                    return fetcher.loadData(priority);
                } catch (Exception ex) {
                    if (fetcher != null) {
                        fetcher.cleanup();
                    }
                    fetcher = loader.getResourceFetcher(model.getMDUrl(), width, height);
                    return fetcher.loadData(priority);
                }
            }

            @Override public void cleanup() {
                if (fetcher != null) {
                    fetcher.cleanup();
                }
            }
            @Override public void cancel() {
                if (fetcher != null) {
                    fetcher.cancel();
                }
            }
        };
    }

    static class Factory implements ModelLoaderFactory<YouTubeVideo, InputStream> {
        @Override public com.bumptech.glide.load.model.ModelLoader<YouTubeVideo, InputStream> build(Context context,
                GenericLoaderFactory factories) {
            return new YTVModelLoader(factories.buildModelLoader(String.class, InputStream.class));
        }
        @Override public void teardown() {
        }
    }
}

@vsahu1986
Copy link
Author

Looks Feasible to my Solution , will try it . Thanks @TWiStErRob

@vsahu1986
Copy link
Author

1 Assuming that if SDUrl failed once, it'll fail the next time - it is not always true , there could be timeout or network error or connection error ,
2 so it's better to cache MDUrl in that case for this video, forever , - If some how I could check it is HTTP_404

@TWiStErRob
Copy link
Collaborator

TWiStErRob commented Oct 5, 2015

I used the default ModelLoader<String, InputStream> for convenience and POC, you can simply write your own DataFetcher (the anonymous inner class above) and do any networking with any library (even two requests one after the other), the key is what you return. Take a look at HttpUrlFetcher which is returned by default.

@gemiren
Copy link

gemiren commented Oct 14, 2016

Is there a way to check the cache when trying to load the fallback url? The example code works great but it always loads the fallback url over the network instead of checking for cache first.

@TWiStErRob
Copy link
Collaborator

With this solution you can't check cache, because there's no Glide load going on. You can however download the fallback image(s) once to your app's directory and then return a fetcher that loads that File.

Alternatively look around the other issues which deal with similar problems, or create a new one if you think your use case is different.

@benibela
Copy link

I have tried to use that above code in my app with okhttp after converting it to kotlin, but it has a real high processor usage after loading an image (300% indefinitely on the emulator).

How could that happen?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants