A while ago, I built a react native App that allowed people to view and save African Fashion Styles. The app simply displays about 400+ african fashion styles and then allow you save the styles you like.
This post isn't really about the app, it's about certain storage complexitiies I had to deal with in the process. Complexities that became simple afterwards.
I will not go deep into the discovery and analysis of the complexities and how I unfruitfully tried solving those problems with the use of RealmDb , Sqlite and AsyncStorage. I will go straight to the eventual simplification of these complexities.
I will like to mention that there are actually a lot of other similar Fashion Gallery Apps already.
So you might ask,
Then why did you build yet another one?.
Well, here is my response
I wanted to create one that had what the users of such apps really wanted: offline Storage , which subsequently helps to limit Data Expenses that occur when you have to always download the images each time you open the app.
I created A Node Server, that housed these images and the code that aids their retrieval. This server will feed the app with these images when the app gets installed and initialzed as it is somewhat wrong, unconventional and "rude" to add 400 images (about 146 mb) to an APK . More so, it will be very much unnecessary to launch a new version of app simply becuase I need to add new images. This helps make the app lighter to download and makes image updates easier without releasing new version.
When the user downloads the app and launches it, it connects to the nodejs server , to download an Object file ( imageDict )that shows the details of this images including their names and path details on same server.
Then it downloads this object file to the device filesystem, this file is about 1kb, so it feels light and appropriate to do that.
After that is done, a function called
fetchAndSave()runs through this object file and uses the details present to download these images to the user's device using
rn-fetch-blobto fetch the files from the remote server , then subsequently using
rn-fetch-blobagain to save each image as a local file. Note: Before each image is called, it checks if image already exist locally to avoid unnecessary overwriting.
Here is a twist, before
fetchAndSave()is called, the app actually starts and the gallery opens. This seems inappropriate becuase you might wonder , if you have not saved , what are you going to display in the gallery but its actually the best feature of the app, in my opinion.
Each Picture Container has a dynamic URI that can either be local or remote. If the image is available offline, the uri becomes an base64 encoded version of the offline image, otherwise the uri is a remote url that fetches the image from the remote server, while the loader gif keeps the viewer in wait.
So that for the life time of using the app, you only have to wait for the each image to load remotely once, every susbequent view of an image will be local and let's not forget
fetchAndSaveis already loading meaning at least 60% of the images would have been offline before you get to them even if you internet is only modest in speed. I tested that.
More so, if you abruptly turn off your internet , and close the app,
fetchAndSave() will not download an image twice when it runs again on a consequent app launch. So, it is very easy to tell the user the exact amount of data he or she will have to expend during the lifetime of the app usage. For now, it is 146mb, which is roughly, the exact size of all the images and object file which acts as the manifest.
All though, I try to keep the user a bit on a prepatory
image loading screen before the gallery opens , this is to avoid bad user experience when the user's internet is pretty bad or turned off , in which case, the user is made aware to
Please turn the internet on.