【问题标题】:Android: SQLite cursor error above 1 MB of database sizeAndroid:超过 1 MB 数据库大小的 SQLite 游标错误
【发布时间】:2013-10-10 20:39:25
【问题描述】:

我正在使用 SQLite 数据库开发应用程序。我有以下代码用于获取数据库的所有值。

ArrayList<String> values=new ArrayList<String>(); 
String[] ColumnNames;
String selectQuery="SELECT * FROM "+tableName;
Cursor cursor=sDataBase.rawQuery(selectQuery, null);
if(cursor!=null && cursor.getColumnCount()>0 && cursor.getCount()>0){
    ColumnNames=cursor.getColumnNames();
    if (cursor.moveToFirst()){
        do{
            String value="";
            for(int i=0;i<cursor.getColumnCount();i++){
                if(value!="")
                    value=value +", \\\""+ColumnNames[i]+"\\\":\\\"" + cursor.getString(i)+"\\\"";
                else
                    value= "\\\""+ ColumnNames[i] +"\\\":\\\"" + cursor.getString(i) +"\\\"";
            }
            value="{" + value + "}";
            values.add(value);
        }while(cursor.moveToNext());
    }
    cursor.close();
}

如果数据库大小超过 1MB,应用就会崩溃。如何获取超过 1 MB 的数据库值?

EDIT1:

Logcat 值:

10-10 14:46:24.863: E/dalvikvm-heap(3248): Out of memory on a 6612888-byte allocation.

EDIT2:

使用字符串缓冲区的代码

   if(cursor!=null && cursor.getColumnCount()>0 && cursor.getCount()>0)
            {
                ColumnNames=cursor.getColumnNames();
                if (cursor.moveToFirst()){
                       do{
                           StringBuffer value= new StringBuffer();
                            value.append("{");
                           for(int i=0;i<cursor.getColumnCount();i++)
                           {
                               if(value.length()>1)
                                   value.append(", \\\""+ColumnNames[i]+"\\\":\\\"" + cursor.getString(i)+"\\\"");
                               else
                                  value.append("\\\""+ ColumnNames[i] +"\\\":\\\"" + cursor.getString(i) +"\\\"");
                           }
                           value.append(value + "}");
                           values.add(value);
                       }while(cursor.moveToNext());
                    }
                    cursor.close();
            }

值 StringBuffer 的长度为 4860024。

【问题讨论】:

  • 什么是崩溃?你可以发布堆栈跟踪吗?
  • @GrahamBorland 我这里粘贴了logcat信息。
  • 为什么需要一次将所有数据库加载到1个字符串中?
  • 我需要执行SELECT_ALL查询并将游标转换为json数据。这是我的要求。而不是像这样使用字符串或字符串缓冲区,我该如何实现呢?

标签: android android-sqlite android-cursor


【解决方案1】:

嗯,很明显,您只是内存不足。您正在使用一系列不可变的String 对象构建数据库的字符串表示形式。

String value="";

每次您进行字符串连接时,value=value +", \\\"" 都会创建一个新的 String 对象。这在内存使用方面非常低效。

尝试使用StringBuilder 代替String,并使用其append() 方法代替字符串连接运算符+。这将允许在单个缓冲区中构建字符串(将根据需要增长),这使得它更有可能适合可用的堆内存。

【讨论】:

  • 我正在开发应用程序,通常是通过javascript调用本机方法。此方法调用将 json 字符串返回到 html 页面。这就是我进行字符串操作的原因。再想一想,我已经阅读了一些描述,android 光标大小为 1MB 的问题。对吗?
  • 对这种情况有什么建议吗?
  • 我不明白你在问什么。您是否进行了建议的更改?解决问题了吗?
  • stackoverflow.com/questions/5406429/… 在此链接中,他们指定光标大小为 1MB。我问这是对的吗?我需要数据库值的 JSON 值,这就是我使用字符串操作的原因。我正在尝试使用 stringbuilder 生成 JSON 字符串。
  • 如果您从 LogCat 发布更多堆栈跟踪,这可能有助于我们确定分配失败是在 SQLite 内部发生,还是与您的字符串连接有关。无论如何,请尝试我的建议,如果有帮助,请告诉我。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-05-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-10-01
  • 1970-01-01
  • 2016-12-19
相关资源
最近更新 更多