Original address: http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2014/1209/2136.html
Offline caching is when the network is unblocked, the data received from the server is saved locally, and the data in the local file is read directly after the network is disconnected.
To save network data locally:
You can write your own way to save the data cost of the file, stored in any directory of the Android system (of course, have permission to do), but in this case the use of the context of the Openfileoutput method is the most convenient and most consistent with our scene, the following The Saveobject method demonstrates how to save data in a local file using Openfileoutput:
saveObject
1 Public Static Booleansaveobject (Serializable ser, String file) {2FileOutputStream fos =NULL;3ObjectOutputStream Oos =NULL;4 Try {5FOS =appcontext.getinstance (). Openfileoutput (file, Appcontext.getinstance (). Mode_private);6Oos =NewObjectOutputStream (FOS);7 Oos.writeobject (Ser);8 Oos.flush ();9 return true;Ten}Catch(Exception e) { One e.printstacktrace (); A return false; -}finally { - Try { the oos.close (); -}Catch(Exception e) { - } - Try { + fos.close (); -}Catch(Exception e) { + } A } at}
Openfileoutput can directly obtain a file path associated with the application (under/data/data/<package name>/files), and then use the ObjectOutputStream in Java io to The serialized object writes ( writeObject
) to the resulting file, you can see that the above implementation process has two key methods:openfileoutput, writeObject
以及调用它们的两个关键对象Context和ObjectOutputStream
. For serialization you can see this article:serialization and deserialization practices for Java objects
This is to save a serialized object locally, what does it have to do with our offline cache for storing network data?
, because most of the data obtained online can be converted to string types, and now the data returned by the server is typically a JSON-formatted string. Strings of type string are actually serializable objects. Here is an example of a server returning JSON data (in fact, Jcodecraeer):
1 {"url": "http://jcodecraeer.com/uploads/soft/android/CodeBox.apk", "Versioncode": "7", " Updatemessage ":" Increased offline cache, classification filtering feature Fixed version compatibility issue "}
Using the Saveobject method above we can save the data locally, in order to be able to remove the file we have to figure out how to name the saved file, if it is a simple article of data, we can directly name the file as the ID of this article, because the ID is unique , in order to not conflict with other data as far as possible, you can also add a prefix to this ID, such as this article is under the Java column we can arc_java_id. If it is a list of articles we can name: Article category _ page number, in short, the principle of naming is can and other offline data differences, there is uniqueness. Why not use URLs as file names? URLs are definitely unique, but URLs do not necessarily conform to the naming conventions of files.
Here's how to read the locally cached data
When we read the cache, we just need to know the file name, and the following ReadObject method is used to read the cached data according to the file name. In fact, a lot of things are corresponding to the data stored above.
readObject
1 /**2 * Read Object3 *4 * @paramfile5 * @return6 * @throwsIOException7 */8 Public StaticSerializable readobject (String file) {9FileInputStream FIS =NULL;TenObjectInputStream Ois =NULL; One Try { AFIS =appcontext.getinstance (). openfileinput (file); -OIS =NewObjectInputStream (FIS); - return(Serializable) ois.readobject (); the}Catch(FileNotFoundException e) { -}Catch(Exception e) { - e.printstacktrace (); -}finally { + Try { - ois.close (); +}Catch(Exception e) { A } at Try { - fis.close (); -}Catch(Exception e) { - } - } - return NULL; in}
Use
The following code demonstrates how to store and read network data using the above knowledge
1String key = "Codelist_" + mcategory.getvalue () + "_" + +page;2String result = "";3 //Cache4 if(httputil.isnetworkconnected ()) {5result =Httputil.http_get (appcontext.getinstance (), URL);6 httputil.saveobject (result, key);7result =(String) httputil.readobject (key);8}Else {9result =(String) httputil.readobject (key);Ten if(Result = =NULL) Oneresult = "Erro"; A}
When the network is unblocked, the data is fetched from the server (), and the HttpUtil.http_get(AppContext.getInstance(), url )
data is saved to local ( HttpUtil.saveObject
), and when the network is unavailable, the cached data is read directly from the local, not interacting with the server.
HttpUtil
This is a network-related tool class, which involves three methods:
1 isnetworkconnected () Determine if the network is available 2 Saveobject above has given the realization 3 ReadObject above has given the realization 4 http_get read server data for the specified URL
而AppContext.getInstance()
是我自己写的,是为了方便在HttpUtil
的静态方法中获得Context对象。
这里的key就是文件名。
Additional requirements
Sometimes we have this requirement that when the user reads the same data source at a specified interval, it gets from the network more than the time interval, and this is done to save the user's traffic, and also avoids the interface delays caused by each fetch of data from the network.
The following implements how to determine whether the server data needs to be refreshed based on the time interval, true indicates no need, false indicates need (very awkward, it is isCacheDataFailure
related to the name):
1 Public Static Booleaniscachedatafailure (String cachefile) {2 BooleanFailure =false;3File data =appcontext.getinstance (). Getfilestreampath (cachefile);4 if(data.exists ()5&& (System.currenttimemillis ()-data.lastmodified ()) >cache_time)6Failure =true;7 Else if(!data.exists ())8Failure =true;9 returnfailure;Ten}
Compare the current time to the modified time of the file, Cache_time is a fixed value (in milliseconds) and you can replace it with any int type.
Add this condition and the code above is changed to:
1String key = "Codelist_" + mcategory.getvalue () + "_" + +page;2String result = "";3 //Cache4 if(Httputil.isnetworkconnected () &&httputil.iscachedatafailure (Key)) {5result =Httputil.http_get (appcontext.getinstance (), URL);6 httputil.saveobject (result, key);7result =(String) httputil.readobject (key);8}Else {9result =(String) httputil.readobject (key);Ten if(Result = =NULL) Oneresult = "Erro"; A}
Perfect
The above steps are sufficient for the general application, but in the case of higher requirements, we also have to consider that over time, the cache data will be more and more, so we need to increase the deletion of expired cache function, the principle is to set a threshold, when the cache is saved, the current cache is determined whether the total is greater than the threshold, If yes, the cache is deleted earlier.
This implementation is a bit complex, you can consider a simpler scenario, periodic check (or the user every time the program is opened) the total amount of cache, when greater than the threshold, prompting the user to actively delete. The concrete implementation is not much to say.
Note: Openfileoutput ()The first parameter of the method is used to specify the file name, cannot contain the path delimiter "/", and if the file does not exist, Android will automatically create it. The created file is saved in the/data/data/<package Name>/files directory, such as:/data/data/cn.itcast.action/files/itcast.txt, by clicking on the Eclipse menu " Window "-" Show View "-" other ", expand the Android folder in the Conversation window, select the File Explorer view below, and then expand/data/data/<package in the File Explorer view The file can be seen in the Name>/files directory.
The second parameter of the Openfileoutput () method is used to specify the mode of operation, with four modes: context.mode_private = 0
Context.mode_append = 32768
context.mode_world_readable = 1
Context.mode_world_writeable = 2
Context.mode_private: As the default mode of operation, which means that the file is private data and can only be accessed by the app itself, in which the content of the write overwrites the contents of the original file, if you want to append the newly written content to the original file. You can use Context.mode_append
Context.mode_append: The mode checks whether the file exists, appends content to the file, or creates a new file.
Context.mode_world_readable and context.mode_world_writeable are used to control whether other apps have permission to read and write to the file.
Mode_world_readable: Indicates that the current file can be read by another application; Mode_world_writeable: Indicates that the current file can be written by another application.
If you want the file to be read and written by another app, you can pass in:
Openfileoutput ("Itcast.txt", context.mode_world_readable + context.mode_world_writeable);
How to implement offline caching in "Go" Android