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

iOS - Caching Image failures #394

Open
KevinColemanInc opened this issue Jan 12, 2019 · 18 comments
Open

iOS - Caching Image failures #394

KevinColemanInc opened this issue Jan 12, 2019 · 18 comments

Comments

@KevinColemanInc
Copy link

KevinColemanInc commented Jan 12, 2019

I am loading 20 images hosted in the USA on a very slow wifi connection (less than 1Mbps) from Asia. In the browser, the images fetch, but its slow.

It seems that FastImage, if the image loading fails (onError is triggered), caches the error instead of trying again later. So when I reload the app, it does not try to refetch the failed images. Only deleting the app and re-launching it again will FastImage be able to fetch the images again.

I don't know iOS / Swift well enough to confirm my hypothesis, but is anyone else seeing this?

@StevenMasini
Copy link
Contributor

StevenMasini commented Mar 20, 2019

@KevinColemanInc I think I am experiencing the same issue as you.

You are indeed right, I investigated the issue and right now on iOS when the "ImageCanvas" (I will call it like this) fail to download an image. Well first it fail silently, the error isn't broadcasted to the RN side, and second it won't try to download the image again.

So my issue is a bit different than yours. I notice this because in my app I have the same picture being display on several screen, and sometime it loads in some screen but not in others.

e.g I have "ImageCanvas1" on page 1 who failed to download the image, then I push page 2 with "ImageCanvas2" who load successfully the picture. When I pop back to page 1 "ImageCanvas1" still haven't loaded the picture.

So I have fixed my issue on my own branch but haven't submit a PR for it yet. Also it's an iOS related issue, this doesn't reproduce on Android as Glide will automatically re-trigger the download if it fails.

But as I said your issue is different, and I should made a fix that handle all the scenario.

I will open a new PR for this, and will keep you updated about it.

@StevenMasini
Copy link
Contributor

@KevinColemanInc I made a Pull Request that should fix your issue #433

@StevenMasini
Copy link
Contributor

@KevinColemanInc I think you can try my PR #433 to see if it fix your problem. Let me know if you have feedback about it.

@KevinColemanInc
Copy link
Author

@StevenMasini I pushed your fix out to production and I haven't seen it crash yet, but I also have not explicitly tested for this case.

@StevenMasini
Copy link
Contributor

@KevinColemanInc Thank you for helping me out.

The PR include an auto-retry logic, so this should solve your problem. Let me know if you figured out anything else or if you have further feedbacks. 👍

@StevenMasini
Copy link
Contributor

@KevinColemanInc Any updates ? Do you still have the crash ?

@evanjmg
Copy link

evanjmg commented Apr 7, 2019

I'm still getting cache misses and/or poor image loading with your fork. Images don't or take a long time to load with excellent internet. There is definitely a lot less memory being used! Thank you so much for the work so far! It's definitely an improvement and using your fork is still way better than using React Native Image or the current version

@StevenMasini
Copy link
Contributor

@evanjmg What kind of caches misses ? Could you describe the problem ?

@fang0rnz
Copy link

hey @StevenMasini I'm having this weird cache behavior on android, does your PR fix this on android as well?

@KevinColemanInc
Copy link
Author

@StevenMasini I had one user report caching failures on iOS. They claimed they couldn't see any images on their profile when they were successfully uploaded to the server. Not sure if this helps :-/ but this might still be a problem.

@evanjmg
Copy link

evanjmg commented May 23, 2019

I'm getting this issue now. Had it today with the latest. Our users report this often. If I go through 100+ images with some failing, they will never load again - even when rerendered on a different view. The only solution is to quit the app and restart it. I don't know the cause, but I'm still trying to create a reproducible demo app. I have a lot of images in my app, use React 16.8 and 0.57.1

@StevenMasini
Copy link
Contributor

@fang0rnz sorry my fix only concern iOS, I don't know anything about native Android 🙃

Let me recap what happened with my fix.

The version v5.3.0 only integrated the fixes related to memory leaks on iOS.

I suggested other fixes back then, related to image cache, but @DylanVann decided to not integrate them because they break the parity between iOS and Android (which I understand and agree).

Nevertheless for my app on production at my company, I am still using my own fork for react-native-fast-image, which integrate two fixes for image cache.

  1. Auto-retry when an image fail to download (will retry 3 times, before giving up). This should solve your issue @evanjmg
  2. Notify all the instance sharing the same url, when one of them succeed to download the resource. This is useful if you have similar images appearing on different screens.

@KevinColemanInc @evanjmg feel free to try my module. You can find the instruction here. Let me know if it helped or not.

@KevinColemanInc
Copy link
Author

KevinColemanInc commented May 24, 2019

@StevenMasini I am using: #27e9e in production and I am still experiencing this issue. I think that matches the latest version of your module.

IMHO, if the image fetch gets a 5xx response, we should try again in a few days, if its a 4xx response, we should stop. If its a timeout, we should just keep trying until we get one of the above http codes with exponential back off. I can't think of any reason why I'd want to cache a timeout failure in my app.

Btw, thanks for working on fixing this!

@antitoine
Copy link

For people who still have a problem with image loading on iOS, here a workarround I used directly in React Native :

const MAX_RELOAD_FAST_IMAGE = 10;

const Image = (props) => {
  const [fastImageKey, setFastImageKey] = useState(1);
  return <FastImage key={fastImageKey} onError={() => {
    if (fastImageKey < MAX_RELOAD_FAST_IMAGE) {
      setFastImageKey(fastImageKey+1);
    } else {
      console.warn('Fast Image error occur, max increment reach, the image won\'t be displayed');
    }
  }} {...props}/>;
};

This work great, but keep in mind that is a very bad approch...
I'm using react-native-fast-image 6.1.1 and RN 0.59.9.

@babyrusa
Copy link

@StevenMasini For the #2 Notify all the instance sharing the same url, when one of them succeed to download the resource. This is useful if you have similar images appearing on different screens.
is this library not supporting caching the same image URL on different screens/components? I've been noticing that since I'm testing my app and notices same images on different components/screens are not cached, the app calls the server every time. I'm not sure if I'm right so I've been searching for the answer.
Thank you

@StevenMasini
Copy link
Contributor

StevenMasini commented Jan 30, 2022

@babyrusa it has been so long since I worked on this issue. I am not working on the project where I used this framework anymore, so it's very hard for me to answer your question.

From what I remember the issue is that you need to find a way for components in other parts of your application to reload when the image is fetched. My solution back then was to use NSNotificationCenter to broadcast the change across the application and make each FastImage instance listen to the change from the native side, which is a workaround but a not a proper react-native solution.

@babyrusa
Copy link

@StevenMasini Thank you for getting back to me. Could you clarify what you meant by "component to reload ", like reload as in rerender/reload the image?

@StevenMasini
Copy link
Contributor

Yes they need to refresh, like a props or stats needs its value to change for the component to reload. Since other components in other views don't won't have any property that will change when the image request will complete download, these components won't reload.

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