Vooruitgang geboekt met CachedNetworkImage

CachedNetworkImage overschrijdt nu de 1,1k Github Stars en behoort nog steeds tot de top pakketten op pub.

Op dit moment bevinden we ons in een wereldwijde gezondheidscrisis als gevolg van het coronavirus. Zoals wij ontwikkelaars al weten, weet de hele wereld inmiddels: "Testen, testen, testen" is cruciaal, en we weten dat we dat moeten doen, maar niet velen van ons hebben voldoende testdekking. Wanneer een pakket zo populair wordt als CachedNetworkImage, is het essentieel om alle gevallen te testen, zodat nieuwe functionaliteit niets kapot maakt voor bestaande gebruikers. CachedNetworkImage overschrijdt nu de 1,1k Github Stars en behoort nog steeds tot de top pakketten op pub.

Testen, testen, testen

Voordat we ons richten op de nieuwe functionaliteit van CachedNetworkImage, willen we de kwaliteit verbeteren van de pakketten die onze mooie afbeeldingen ondersteunen, flutter_cache_manager. Voor een pakket dat door zoveel mensen wordt gebruikt, had het schrikbarend weinig tests: 0. We zijn trots om aan te kondigen dat we de testdekking van 0% naar 81% hebben gebracht in de laatste release. Naast het testen hebben we ook veel regels toegevoegd in het bestand analysis_options.yaml, die niet eens bestonden, waardoor we een aantal potentiële bugs konden oplossen. Het kan niet genoeg benadrukt worden hoe belangrijk het is om op zijn minst een minimale set analyse-opties toe te voegen en om vroegtijdig tests te schrijven voor je code. Een uitstekende plaats om te beginnen met de analyse-opties is het toevoegen van de pedante set zoals geadviseerd door het dart team.


Updates over uw downloadvoortgang

Een van de dingen die we herschreven hebben met de hulp van de gemeenschap is de FileFetcher. Voorheen kon je je eigen FileFetcher leveren om de standaard http client te veranderen, maar je kon alleen full-size inhoud en headers leveren. Deze opzet maakt het inefficiënt en moeilijk te beheren. Als je bijvoorbeeld de max-age van je object wilt veranderen, moet je de headers veranderen, wat niet de bedoeling is. De nieuwe FileService vraagt je om alle headers eruit te halen, maar geeft je ook de mogelijkheid om ze te manipuleren zoals je wilt. Als u bijvoorbeeld een bepaalde bestandsextensie verwacht die niet overeenkomt met het http content-type, kunt u dat doen. We verwachten ook niet langer de volledige inhoud, maar een stream van de inhoud. Wanneer u nog steeds de nu afgeschreven FileFetcher gebruikt, zal de inhoud worden aangeleverd als een stream met slechts één emitterende waarde.


De inhoudsstroom heeft twee gevolgen voor de manier waarop de inhoud wordt behandeld. Ten eerste schrijft de bibliotheek de inhoud rechtstreeks naar een bestand op schijf, terwijl de inhoud van de webserver naar de toepassing wordt gestreamd. Hierdoor gebruikt de bibliotheek minder geheugen, omdat zij niet langer het hele bestand in het geheugen hoeft te bewaren voordat het wordt opgeslagen. In de oude situatie zou dit een aanzienlijk risico inhouden. Vroeger hield de CacheManager de bestandsnaam constant tijdens het bijwerken van de inhoud. Als je een verouderd bestand in je cache had en de server gaf je een update, dan zou die het verouderde bestand overschrijven. In de oude situatie riskeerden we alleen een IO-uitzondering om je oude bestand te verliezen. In de nieuwe situatie lopen we het risico dat een onstabiele internetverbinding het downloaden en opslaan van het bestand mislukt. Dus nu slaan we de gegevens altijd op in een nieuw bestand, en wanneer dat bestand met succes is opgeslagen, werken we de cache-informatie bij en verwijderen we het oude bestand. Dit hele proces van het veranderen van de inhoud in een stream is zoveel gemakkelijker gemaakt door de tests die we eerder hebben geschreven, dat we heel gemakkelijk de meeste gevallen konden testen en er zeker van zijn dat het werkt zoals bedoeld.

Deze verandering van inhoud naar een stream gaf ons ook de mogelijkheid voor een veelgevraagde feature in CachedNetworkImage: de download voortgang. Omdat we al een stream hebben, kunnen we die informatie gemakkelijk aan de CachedNetworkImage leveren. In CachedNetworkImage hebben we nu de optie toegevoegd om een voortgangsindicator als deze toe te voegen:


We hebben met opzet een progressIndicatorBuilder toegevoegd aan de bestaande placeholder, omdat het gedrag anders is. De voortgangsindicator wordt heel vaak herbouwd bij elke statusupdate die hij ontvangt, terwijl de placeholder één keer wordt gebouwd en bewaard tot het beeld volledig is opgehaald. Wanneer u de voortgang niet gebruikt om aan de gebruiker te tonen, is de placeholder dus de efficiëntere en geprefereerde manier. De download voortgang geeft je de gedownloade bytes, de totale grootte van het bestand, en de voortgang als percentage. Zie de doc voor meer informatie.

ContentTypes

Wat de bibliotheek echter niet oplost, is gewoon verkeerde inhoud. Dit klinkt vanzelfsprekend, maar toch krijgen we veel verzoeken daartoe. Er zijn twee soorten dingen die vaak fout gaan. Ten eerste levert de server het verkeerde inhoudstype? Ik heb servers gezien die mp3-bestanden aanleverden met content-type application/octet-stream. Daar willen we niet eens aan beginnen, dus zorg ervoor dat uw server de juiste headers levert voor de inhoud die u opvraagt. Als u geen toegang hebt tot de server, kunt u altijd overwegen de bestanden te downloaden en ze zelf op uw server op te slaan. Of, als u het inhoudstype van tevoren weet, kunt u nu de fileExtension manipuleren door uw FileService te leveren, zoals eerder verteld.

Het tweede wat de bibliotheek niet voor u kan oplossen is als u een afbeelding verwacht maar een html-pagina downloadt. Bijvoorbeeld, deze url ziet eruit als een afbeelding maar is eigenlijk een HTML-pagina met een afbeelding erop:

https://github.com/flutter/flutter/blob/master/examples/flutter_view/assets/flutter-mark-square-64.png

Zorg altijd voor een correcte link naar de afbeelding, zodat alleen de afbeelding wordt gedownload. Sommige servers serveren geen 404 statuscodes wanneer een afbeelding niet wordt gevonden, maar een 404 webpagina met een statuscode 200. Dit kan ook leiden tot onverwachte resultaten, omdat de CacheManager denkt dat het bestand met succes is gedownload en niet zal proberen het bij te werken voordat de max-age is bereikt. Zorg er dus altijd voor dat de server de informatie verzendt zoals de webstandaarden dat verwachten.

En vervolgens

De in dit artikel besproken wijzigingen zijn uitgebracht als flutter_cache_manager 1.2, en de voortgangsindicator kan gebruikt worden met cached_network_image 2.1. Nu we de kwaliteit van de CacheManager grotendeels hebben verbeterd, kunnen we verder met het verbeteren van de kwaliteit van CachedNetworkImage. Door het hele proces opnieuw te doorlopen, zullen we tests schrijven, de kwaliteit van de code verbeteren, en functies toevoegen wanneer de mogelijkheden zich voordoen. Het leggen van een goede basis zal ons de mogelijkheid geven om in de toekomst snel nieuwe functies toe te voegen.