问题
I have an android application that display data from my external Database so from several tables. Everything work fine while internet connection is available (all data come from URL link and they are been parsed with volley). But how can I save and load lastest data when internet is not available.
What is the best way to do that. Im new in android....
Please help.
回答1:
Normally Volley and also HttpStack it uses allows you to seamlessly cache responses. This however depends on your responses and requests. Those cache strategies obeys http cache definition. If You want to have different behavior for Volley you can just override this part. basically when you create a request you can override
protected Response<String> parseNetworkResponse(NetworkResponse response) {
and instead of
return Response.success(parsed, HttpHeaderParser.parseCacheHeaders(response));
you do
long now = System.currentTimeMillis();
Cache.Entry entry = HttpHeaderParser.parseCacheHeaders(response);
entry.ttl = now + 30l * 24 * 60 * 60 * 1000; //kepps cache for 30 days
//entry.softTtl = now + 30l * 24 * 60 * 60 * 1000; //will not refresh for 30 days
return Response.success(parsed, entry);
Which basically will refresh the cache every time the server specifies so but will always return the cache for 30 days unless changes .
Note that here you may receive 2 callbacks in response or in one response and 1 error(in case of no network). the first one will be the cache.
UPDATE:
if you add (which is commented in the example above):
entry.softTtl = now + 30l * 24 * 60 * 60 * 1000; //will not refresh for 30 days
this will affect the refresh of the cache. in this case it wont event try to refresh the cache for 30 days. In that case you will return 1 response.
Note that I never would recommend solution like this because cache needs to be updated, especially if you want to fake cache on POST requests as in your case.
Receiving 2 callbacks is not really an issue as you can handle this seamlesly for the user and update UI when needed. also if you want to have more control you can know which one is from the cache and which one form the network by implementing your
ResponseDelivery
or extend
ExecutorDelivery
and then check for the param
mResponse.intermediate
and decide what to do then. ResponseDelivery is the one which calls the callbacks.
Update
similar question and examples here
回答2:
if you have to store only small chunk of data then use SharedPreferences If you have large data then use SQLite
Use below code to create and update SQLite DB
public class SqlMangaeMenu
{
SQLiteDatabase db1 = null;
private static String DBNAME = "YourLocal.db";
Context gcntxt;
public SqlMangaeMenu(Context cntxt)
{
// TODO Auto-generated constructor stub
gcntxt=cntxt;
db1 = cntxt.openOrCreateDatabase(DBNAME, Context.MODE_PRIVATE,null);
db1.execSQL("CREATE TABLE IF NOT EXISTS mytbl(appid varchar PRIMARY KEY,appname varchar,iconcode varchar,msgidentfier varchar,scode varchar,image blob,imagehdr blobhdr); ");
}//EOF Constructor
public void insertContent(String appid,String appname,String iconcode,String msgidentifier,String scode,Bitmap bmp,Bitmap bmphdr)
{
ContentValues contentValues = new ContentValues();
contentValues.put("appid", appid);
contentValues.put("appname", appname);
contentValues.put("iconcode", iconcode);
contentValues.put("msgidentfier", msgidentifier);
contentValues.put("scode", scode);
byte[] blob = null,blobhdr=null;
if(bmp!=null)
{
ByteArrayOutputStream outStr = new ByteArrayOutputStream();
bmp.compress(CompressFormat.PNG, 100, outStr);
blob = outStr.toByteArray();
}
contentValues.put("image", blob);
if(bmphdr!=null)
{
ByteArrayOutputStream outStr1 = new ByteArrayOutputStream();
bmphdr.compress(CompressFormat.PNG, 100, outStr1);
blobhdr = outStr1.toByteArray();
}
contentValues.put("imagehdr", blobhdr);
Log.d("db", "SQL Writing"+appid+appname+iconcode+msgidentifier+scode);
try {
// db1.insert("mytbl",null,contentValues);
db1.insertWithOnConflict("mytbl", null, contentValues,SQLiteDatabase.CONFLICT_IGNORE);
} catch (Exception e)
{
// TODO: handle exception
}
db1.close();
}//EOF insertContent
// Deleting single contact
public void Delete_appid(String id)
{
db1.delete("mytbl", "appid" + "=" + id, null);
db1.close();
}//EOF Delete_appid
public void readAppId()
{
MyApplication.dbappid=new ArrayList<String>();
String appid;
try
{
Cursor c = db1.rawQuery("SELECT * FROM mytbl", null);
//Cursor c = db1.rawQuery("SELECT MAX(ID) FROM mytbl", null);
if(c!= null)
{
if (c.moveToFirst())
{
do {
appid=c.getString(c.getColumnIndex("appid"));
MyApplication.dbappid.add(appid);
}while(c.moveToNext());
}
}
Log.d("db", "SQL Reading");
db1.close();
}
catch(Exception e)
{
System.out.println(e);
}
}//EOF readAppId
public void readDataandImage()
{
Bitmap image=null,imagehdr = null;
//Bitmap images
MyApplication.dbimg=new ArrayList<Bitmap>();
MyApplication.dbhdrimage=new ArrayList<Bitmap>();
//String
MyApplication.dbappname=new ArrayList<String>();
MyApplication.dbappid=new ArrayList<String>();
MyApplication.dbiconcode=new ArrayList<String>();
String appname,appid,iconcode;
try
{
Cursor c = db1.rawQuery("SELECT * FROM mytbl", null);
if(c!= null)
{
if (c.moveToFirst())
{
do {
image=null;imagehdr=null;
byte[] blob = c.getBlob(c.getColumnIndex("image"));
byte[] blobhdr = c.getBlob(c.getColumnIndex("imagehdr"));
appid=c.getString(c.getColumnIndex("appid"));
appname=c.getString(c.getColumnIndex("appname"));
iconcode=c.getString(c.getColumnIndex("iconcode"));
if(blob!=null)
{
image = BitmapFactory.decodeByteArray(blob, 0, blob.length);
}
if(blobhdr!=null)
{
imagehdr = BitmapFactory.decodeByteArray(blobhdr, 0, blobhdr.length);
}
//Images
MyApplication.dbimg.add(image);
MyApplication.dbappid.add(appid);
//String
MyApplication.dbappname.add(appname);
MyApplication.dbiconcode.add(iconcode);
MyApplication.dbhdrimage.add(imagehdr);
}while(c.moveToNext());
}
}
Log.d("db", "SQL Reading");
db1.close();
}
catch(Exception e)
{
System.out.println(e);
}
}//EOF readDataandImage
public int dbRowCount()
{
int rowcnt=0;
String countQuery = "SELECT * FROM mytbl";
//SQLiteDatabase db = this.getReadableDatabase();
Cursor cursor = db1.rawQuery(countQuery, null);
rowcnt = cursor.getCount();
cursor.close();
db1.close();
Log.d("db", "Numrecs"+rowcnt);
return rowcnt;
}//EOFdbRowCount
}
where MyApplication is a static class to hold the read values.
来源:https://stackoverflow.com/questions/36406399/load-local-data-if-internet-connection-not-available