For people visiting Data.gov for a little while there, this is what met them.
From a developer perspective, this meant the data housed there, the same data many of those developers had built apps around, was inaccessible. Unless they took some action to ensure their continued access that meant their app had no data or partial data. For those developers, at that time, their app was effectively dead.
While the above example is a rare event, service outages are not. What happens if your user’s internet goes down, but the power stays on? How about a DNS failure? Slow connections? What about entering a subway tunnel? Plenty of regular, everyday events can cause your app to be unconnected.
As a developer you need to ensure access to your data, and the easy answer to that is to keep a local cache. For Windows 8 and Windows Phone 8 we have two options in this regard: files and local app data. While both are accessed via ApplicationData and both are very useful, they have very different implementations.
With local app data, we can serialize any object (so long as it’s serializable) and store it. The app does this with a simple Key-Value pair (KVP) as highlighted in the example below.
For arguments sake, we’ll say we have an app that lists the titles of various apps. Rather than creating an independent file to hold this data, we’ve decided to store it in the local app data. Here we check we haven’t yet added a KVP for the given app, and we assign the true value to it so we can find out later we have installed it. It’s stored, accessible after closing and re-launching the app, and as long as we don’t uninstall the app (or overwrite/remove the data) it’s available to us.
So why would we choose local app data for this? Well, there’s flexibility. Each KVP is a string and an object, respectively. I can happily save a list in one KVP and an image (size permitting) in another and don’t need to take any special action. In the case of single variables, it’s a good idea to go this route as it’s not very efficient to create, save, and load a file for one or two pieces of data. Also, due to the sandboxing of Windows 8 and Windows Phone 8, I know it’s kept separate from other apps. It truly is local to this app only.
Of course, you may, for various reasons, want to store your data in a file. You can even save that file locally to the app so it’s protected by the sandboxing. Of course, you could also save it outside the sandboxing for access from other apps. This external access is the major difference from local app data. By saving a data source outside the app you allow other apps to access it as well. If you use a single data source in multiple apps, you don’t need to download it once for each. Of course, it also means the file is easily accessed by the user, so tread cautiously.
From the perspective of open data and ensuring access, you can see why all this is very important. By keeping local versions of the files, and only overwriting them with newer versions, we always have access to something. Out of date data will allow your app to run, while no data will not.
Further, we could mix and match these storage methods for efficiency. For argument’s sake, let’s say your data source allows you to call changes since a given version via the ID number. Why not save the data in a file and keep the version ID in a KVP? This way you don’t have to load a file every time you want to check for new data.
Now that we have our heads wrapped around the device, let’s get open our minds to the user experience. One of the beauties of Windows 8 is that all your Windows 8 devices can share your settings. Even if a user borrows a friend’s laptop or tablet, they can log into their Windows 8 experience. This means they can have the same desktop and backgrounds, access to their SkyDrive, and the same store profile. And their apps can access the same settings via RoamingSettings.
The great part about RoamingSettings is that it’s accessed very similarly to LocalSettings.
As the example shows, there really isn’t any difference in how we access the RoamingSettings versus the LocalSettings. There is a difference in the requirements, however. It goes without saying that RoamingSettings requires an internet connection to work. Further, if you try to put in too much data it simply won’t save it to the cloud. This is to prevent overloading a data connection or slow down performance. So what are the caps? As we can see at ApplicationData.RoamingSettings, we have a limit of 8KB per setting and 64KB per composite setting. And don’t worry. If you think you’re getting too close to the cap, or you simply don’t want to clutter up RoamingSettings with unnecessary data, you can use RoamingSettings.values.Remove() to clear out the old information.
Now you may be thinking that RoamingSettings are great, but you would really like to have the same ability with files. Well, Microsoft thought that too, so you do. Your RoamingFolder allows you to have an app-specific cloud storage solution for your files. Be very careful when using this. This will use whatever data connection your user is on (wi-fi, wired, or cellular if tethered [RoamingFolders aren’t implemented for Windows Phone]) so care should be taken not to be over using that connection. Some user’s connections will be very slow, or could have a pay cap, and hitting these limits can be the same as a service outage.
Square Pegs, Round Holes
With all those options in front of us, it can be a bit daunting deciding what method to use in a given situation. That said, there are a few things to keep in mind.
- Due to possible limits on a user’s data connection, you don’t want to be downloading any more materials than absolutely necessary, especially if you’re only going to overwrite something immediately after you have it. Further, if you want to defend against service outages storing files in the cloud may not be as solid a defence as you’d like. If the outage is local to the user, it doesn’t matter where the data lives if it’s not on their computer.
- If you have the file already because you’ve locally cached it, you really don’t need to store the derived Lists or IEnumerables (or what have you) in LocalSettings or RoamingSettings. Take care of that processing during app startup and implement an extended splash screen to give the user a good experience. Besides, to update the data you need to download the file. If, however, you need to do some heavy data manipulation or combinations, storing the resulting collections in a serialized file is definitely justified.
As for when to use LocalSettings or RoamingSettings for simple data and not files, think about these questions: Does the user need this data regardless of what they’re doing, or where they are? Is this data derived from another source?
- If the answer to the first question is yes, RoamingSettings is what you want. By keeping the data in the cloud you keep it current across all platforms and that maintains the user experience. An example for this is if the user has a favourites list: It’s likely they want that list reflected across devices.
- If you answer the second with yes, go with LocalSettings or simply derive the data each time as needed (it’ll depend on how intensive it is to derive the data). By keeping it out of the cloud you don’t need to worry about internet connections, download speeds, or other possible hangups.
And above all, remember: You should always have a very good reason for using the user’s time, resources, or bandwidth and should try your hardest to keep that usage to a minimum.