【问题标题】:Load local data if internet connection not available如果互联网连接不可用,则加载本地数据
【发布时间】:2016-04-19 21:03:45
【问题描述】:

我有一个 android 应用程序,它显示来自我的外部数据库的数据,因此来自多个表。在互联网连接可用的情况下一切正常(所有数据都来自 URL 链接,并通过 volley 进行解析)。但是,当互联网不可用时,如何保存和加载最新数据。

最好的方法是什么。我是安卓新手....

请帮忙。

【问题讨论】:

  • 你可以使用 SharedPreferences
  • 请举例

标签: android network-programming android-volley


【解决方案1】:

通常 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 个回调并不是真正的问题,因为您可以为用户无缝处理此问题并在需要时更新 UI。此外,如果您想拥有更多控制权,您可以通过实现您的

来知道哪个来自缓存,哪个来自网络

响应传递

或扩展

ExecutorDelivery

然后检查参数

mResponse.intermediate

然后决定做什么。 ResponseDelivery 是调用回调的那个。

更新

类似的问题和例子here

【讨论】:

  • 我用这个link 试试你的解决方案,它工作正常,但是当有一个活动片段显示取决于参数(GET 或 POST)的信息时,缓存呢?
  • caches 使用缓存键,默认情况下是包含所有参数的 url,因此对于 get,您将为不同的参数提供不同的缓存。对于帖子,您可以根据需要自定义它,甚至可以覆盖缓存键
  • 好的 djojo。但是根据 [链接] (stackoverflow.com/questions/31897189/…) 给了我一个问题。数据在列表视图中显示两次。似乎当连接可用时,来自 url 显示的数据以及条目缓存数据显示。那怎么解决不了。谢谢
  • 1) 这个解决方案形式的链接与我的相同,只是我的简化并重用缓存头的默认解析,只是稍后调整对您重要的内容。 2)我更新了答案,但是用两个词你可以使用 softTtl 来抑制第二个回调,但我建议只在你的逻辑中处理 1 个回调更新单个元素但不要添加另一个元素。
  • 请根据链接解决方案和你的解决方案,你能给我一个完整的代码或一个清晰的例子,因为我在列表视图中总是得到两个数据(缓存和 url)。没有网络时如何调用缓存数据,网络正常时只显示url数据。
【解决方案2】:

如果您只需要存储一小部分数据,请使用 SharedPreferences 如果您有大量数据,请使用 SQLite

使用以下代码创建和更新 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 

}

其中 MyApplication 是一个静态类,用于保存读取的值。

【讨论】:

    猜你喜欢
    • 2019-12-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-17
    • 2013-11-30
    • 1970-01-01
    • 2021-11-14
    • 2011-11-13
    相关资源
    最近更新 更多