我有时在我的日志中看到这个错误:
从具有 0 行、64 列的 CursorWindow 中读取第 0 行、第 0 列失败。
首先,需要讲述一下背景。我的应用程序运行在我们组织中的许多设备上。目前,它主要在大约 20 台 Samsung Note 8 设备、2 台 Samsung Note 10.1 设备以及其他几个设备上运行。到目前为止,这个问题只发生在 2 台 Note 8 设备上。对于所有其他设备,它似乎都能正常工作。
应用程序的工作原理是:用户使用应用程序收集信息,如文本、照片、签名等等,并将所有这些内容存储/插入到 SQLite 数据库中,作为提交表中的一行。提交表共有 64 列,以适应每个字段的收集。总是在后台运行一个同步方法(它是一个 AsyncTask,在 runnable thread 内执行,因此即使关闭应用程序,仍会同步数据,除非您从 Android 任务管理器中滑动关闭它),该方法将数据同步到远程服务器,并每隔 10 秒检查一次是否需要进行同步,例如如果插入了新的提交,那么它将开始同步该提交。当提交成功与服务器同步并收到成功响应后,它将从设备的数据库中删除。到目前为止,它一直表现良好,并成功同步了数千个提交等等。然而,偶尔会有一两台特定的 Note 8 平板电脑出现该问题。我已经尝试过很多次来重新创建这个错误,但每次测试都能正常工作,我已经尝试过各种情况来测试它。
我的代码有数千行,所以我将尽可能保持其相关性。首先,这是可运行代码的相关代码:
public Runnable myRunnable = new Runnable()
{
@Override
public void run()
{
count ++;
if(count >= 10)
{
android.util.Log.w(" SYNC ", "---------------");
android.util.Log.w(" SYNC ", "Checking if sync method is busy");
if(!syncBusy)
{
android.util.Log.w(" SYNC ", "Sync method OPEN");
doSync();//This will start doing sync.
count = 0;
}
else
{
android.util.Log.w(" SYNC ", "Sync method BUSY, will try again in 10 seconds");
android.util.Log.w(" SYNC ", "---------------");
}
}
if(count == 1 && !syncBusy)
{
checkSubmissionsLefttoSync();
}
mHandler.postDelayed(myRunnable, 1000);
}
};
然后,doSync()方法是我上传的地方,也是我遇到错误的地方。它有1000多行,所以我不想在这里发布代码。我可以说的是,除了产生上述错误的一两个例外设备外,它对所有设备都能百分百工作。
此外,在sync方法中实际遍历数据库的部分会被发布:
databaseHelper = new Handler_Database(this);
Cursor cursor2 = databaseHelper.getAllUnsyncedSubmissions();
if(cursor2.getCount() > 0)
{
if(cursor2.moveToFirst())
{
do
{
try
{
//doing lookups here and populating sync arrays
}
catch (IllegalStateException e)
{
//Do Nothing
}
catch (NullPointerException e)
{
//Do Nothing
}
}
while(cursor2.moveToNext());
}
else
{
}
}
else
{
}
cursor2.close();
databaseHelper.close();
我注意到了另一个问题,但我不确定它是否是一个问题,当我运行应用程序时,logcat会输出以下行约6或7次:
我的应用程序启动时会显示自己的警告消息,这些消息仅显示一次。然而,数据库版本和其他信息被多次写入logcat。这是个问题吗?这是否意味着我的数据库存在某种错误,创建了多个实例?12:48:11.115 7416 #7416 DEBUG SQLiteOpenHelper DB version : 60
所有应用程序都使用来自playstore的已签名apk进行更新。我的onUpgrade方法如下:
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)
{
// Drop older table if existed
db.execSQL("DROP TABLE IF EXISTS " + TABLE_SUBMISSIONS);
// Create tables again
onCreate(db);
}
这对于其他平板电脑和设备都很好用。它们都可以自动从Play商店更新并继续正常工作。然而,为什么logcat会输出那些行多次呢?这可能是我在本贴开头提到的错误的一部分吗?任何可能的见解都将不胜感激。我已经为此苦苦挣扎了几周,但无法在我的代码中找到任何错误。
更新 1:
我刚看到这个警告:我想这可能是我的问题的根源。有什么有效的解决方法吗?08:30:58.710 16745 #16745 WARN CursorWindow Window is full: requested allocation 307333 bytes, free space 249426 bytes, window size 2097152 bytes
更新 2:
我认为一个解决办法可能是限制我从游标中检索的列。例如,所有小文本值/列。然后,在确定占用太多空间的每个列之后,创建一个新的查询。你认为这是一个解决方案吗?有人吗?更新 3:
这可能起作用,我想我会在最初的游标回收后使用单独的游标来处理大字段。就像这样(我只是写了一些伪代码):Cursor c = db.rawQuery("SELECT Column1, Column2 .... FROM table " + ... , ...);
解决方案:
你可以在这里查看我的解决方案:https://stackoverflow.com/a/26797130/1518916