背景粘性并发标记扫描GC sqlite数据库的无限循环

时间:2018-12-30 11:06:56

标签: android sqlite

我在应用程序中使用SQLite数据库,我试图添加一个以哈希图的形式从数据库中获取一些数据的函数

 public HashMap<Integer, ArrayList<OrderCustomer>> getOrderCustomers (){
        SQLiteDatabase db = getReadableDatabase();
        String query = "SELECT * FROM " + TABLE_ORDER_CUSTOMER + " ;";
        Cursor cursor = db.rawQuery(query,null);
        cursor.moveToFirst();
        HashMap<Integer, ArrayList<OrderCustomer>> result = new HashMap<>();

        while (!cursor.isAfterLast()){
            int fkOrder = cursor.getInt(cursor.getColumnIndex(OC_FK_ORDER));
            int fkCustomer = cursor.getInt(cursor.getColumnIndex(OC_FK_CUSTOMER));
            double cost = cursor.getDouble(cursor.getColumnIndex(OC_COST));

            OrderCustomer orderCustomer = new OrderCustomer(fkOrder, fkCustomer);
            orderCustomer.setCost(cost);

            ArrayList<OrderCustomer> orderCustomers = new ArrayList<>();

            if(result.containsKey(fkOrder)){
                orderCustomers = result.get(fkOrder);
                result.remove(fkOrder);
            }
            orderCustomers.add(orderCustomer);
            result.put(fkOrder, orderCustomers);
    }
        db.close();
        cursor.close();

        return result;
}

但是自从我添加了此功能以来,该应用为我带来了以下无限循环:

Background sticky concurrent mark sweep GC freed 133964(3MB) AllocSpace objects, 0(0B) LOS objects, 7% free, 29MB/31MB, paused 34.098ms total 149.711ms

并且不会启动,有时会崩溃,并且OutOfMemoryError指向该函数。 导致该错误的函数出了什么问题? PS:首次安装后,该应用程序可以正常运行,这可能会有所帮助。 请询问您是否还有更多信息。

1 个答案:

答案 0 :(得分:1)

您的问题是,您永远不会移动到第一行,因此光标永远不会在最后一行之后,从而实现了无限循环。可以通过在循环的下一次迭代之前添加cursor.moveToNext();来解决此问题。

但是,我建议使用更简单的

while(cursor.moveToNext) {
    ....... 
}

代替使用(请参阅注释以获取修复程序)

cursor.moveToFirst();
while (!cursor.isAfterLast()){

    cursor.moveToNext(); // <<<<<<<<<< what was omitted
}
  • 如果未提取任何行,则上述操作将导致失败,因为未检查moveToFirst是否成功。

因此,我建议将您的代码更改为:-

public HashMap<Integer, ArrayList<OrderCustomer>> getOrderCustomers (){
    SQLiteDatabase db = getWritableDatabase();
    String query = "SELECT * FROM " + TABLE_ORDER_CUSTOMER + " ;";
    Cursor cursor = db.rawQuery(query,null);
    HashMap<Integer, ArrayList<OrderCustomer>> result = new HashMap<>();

    while (cursor.moveToNext()){
        int fkOrder = cursor.getInt(cursor.getColumnIndex(OC_FK_ORDER));
        int fkCustomer = cursor.getInt(cursor.getColumnIndex(OC_FK_CUSTOMER));
        double cost = cursor.getDouble(cursor.getColumnIndex(OC_COST));

        OrderCustomer orderCustomer = new OrderCustomer(fkOrder, fkCustomer);
        orderCustomer.setCost(cost);

        ArrayList<OrderCustomer> orderCustomers = new ArrayList<>();

        if(result.containsKey(fkOrder)){
            orderCustomers = result.get(fkOrder);
            result.remove(fkOrder);
        }
        orderCustomers.add(orderCustomer);
        result.put(fkOrder, orderCustomers);
    }     
    cursor.close();
    db.close();
    return result;
}
  • 注意事项
    • getReadableDatabase在大多数情况下将获得可写的数据库
    • cursor.moveToFirst()已被删除(当光标位于第一行之前的位置(即-1)时,moveToNext将移至第一行)。
    • 应该在关闭数据库之前关闭游标