Загрузить локальные данные, если интернет-соединение недоступно
У меня есть приложение для Android, которое отображает данные из моей внешней базы данных из нескольких таблиц. Все работает нормально, в то время как подключение к интернету доступно (все данные поступают по URL-ссылке, и они были проанализированы с залпом). Но как я могу сохранить и загрузить последние данные, когда Интернет недоступен.
Каков наилучший способ сделать это. Я новичок в Android....
Пожалуйста помоги.
2 ответа
Обычно Volley и HttpStack, который он использует, позволяют беспрепятственно кэшировать ответы. Это, однако, зависит от ваших ответов и запросов. Эти стратегии кэширования подчиняются определению http-кэша. Если вы хотите иметь другое поведение для Volley, вы можете просто переопределить эту часть. в основном, когда вы создаете запрос, вы можете переопределить
protected Response<String> parseNetworkResponse(NetworkResponse response) {
и вместо
return Response.success(parsed, HttpHeaderParser.parseCacheHeaders(response));
ты сделаешь
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);
Который в основном будет обновлять кэш каждый раз, когда сервер так указывает, но всегда будет возвращать кэш в течение 30 дней, если не произойдет изменений.
Обратите внимание, что здесь вы можете получить 2 обратных вызова в ответе или в одном ответе и 1 ошибку (в случае отсутствия сети). первым будет кеш.
ОБНОВИТЬ:
если вы добавите (что прокомментировано в примере выше):
entry.softTtl = now + 30l * 24 * 60 * 60 * 1000; //will not refresh for 30 days
это повлияет на обновление кэша. в этом случае событие не будет пытаться обновить кэш в течение 30 дней. В этом случае вы вернете 1 ответ.
Обратите внимание, что я никогда не рекомендовал бы подобное решение, потому что кэш нужно обновлять, особенно если вы хотите подделать кеш на POST-запросах, как в вашем случае.
Получение 2 обратных вызовов на самом деле не является проблемой, так как вы можете обрабатывать этот случай для пользователя и обновлять пользовательский интерфейс, когда это необходимо. Кроме того, если вы хотите иметь больше контроля, вы можете узнать, какой из кеша, а какой образует сеть, путем реализации вашего
ResponseDelivery
или продлить
ExecutorDelivery
а затем проверить на параметр
mResponse.intermediate
и решить, что делать потом. ResponseDelivery - это тот, который вызывает обратные вызовы.
Обновить
Подобный вопрос и примеры здесь
Если вам нужно хранить только небольшой кусок данных, используйте SharedPreferences. Если у вас большие данные, используйте SQLite.
Используйте приведенный ниже код для создания и обновления БД SQLite
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
}
где MyApplication - статический класс для хранения прочитанных значений.