1

我的程序为我的 GridView 使用 CursorAdapter ,并使用 AsynTask 获取 curosr 并刷新我的视图。

在任务的 doinbackgroud 中,我在 sqlite 中执行查询,并获取光标。在任务的 onPostExecute 中,我使用 CursorAdapter.changeCursor 通过新数据刷新我的视图。

但是由于游标有太多关于数千行的数据,所以在 changeCursor 时 ui 线程被阻塞。

光标不使用 lasy 策略吗?我应该怎么做?

我的代码:

private class ToNodeTask extends AsyncTask<Long, Void , OrgManager.CursorDataInfoInStruct >{

    protected Long taskId = null;

    @Override
    protected  OrgManager.CursorDataInfoInStruct doInBackground(Long... params) {
        taskId = params[0];
        OrgManager.CursorDataInfoInStruct info = OrgManager.getInstance().getCursorDataInfoInStruct(taskId);
        if(info != null){
            if(info.members != null){
                info.members.getCount();
            }
            if(info.nodes != null){
                info.nodes.getCount();
            }
        }

        return info;
    }

    @Override
    protected void onPostExecute( OrgManager.CursorDataInfoInStruct result) {
        super.onPostExecute(result);

        if(result != null){

            gridAdapter.changeCursor(result.members);
            departmentAdapter.changeCursor(result.nodes);
        }

    }

}

//OrgManager.java

public CursorDataInfoInStruct getCursorDataInfoInStruct(long structId){
        OrgStruct struct = getStruct(structId);
        if(null == struct && structId != 0) return null;

        CursorDataInfoInStruct info = new CursorDataInfoInStruct();
        info.parent = struct;
        info.nodes = getDb().rawQuery(SQL_QUERY_NODE_DATA_IN_SRUCT, new String[]{String.valueOf(structId)});
        info.members = getDb().rawQuery(SQL_QUERY_MEMBER_DATA_IN_SRUCT ,  new String[]{String.valueOf(structId)});

        return info;
    }

info.members 和 info.no​​des 的类是 Cursor。

当 info.members 有大约 2000 行时,它会在我的设备中阻止我的 ui 线程大约四秒钟。我在工作线程中调用 cursor.getCount() ,但它没有帮助。

4

2 回答 2

1

有关大量数据,请参阅将光标与 ListView 适配器一起使用

当您使用 changeCursor 时,它会调用 Cursor.getCount() -“这会强制完全执行查询并计算结果”。

我这样做了 - 在后台线程中准备光标并获取它的长度(从 db 中提取数据将在此处执行):

stopManagingCursor(cursor);
cursor = dbAdapter.getData(query);
startManagingCursor(cursor);
count = cursor.getCount();

在 UI 线程 (onPostExecute) 中更改光标:

recordsAdapter.changeCursor(cursor);

在这种情况下,更改光标不会冻结 UI 线程。

于 2013-11-20T09:58:58.270 回答
0

我知道这篇文章很旧,但它可能对某人有用,我以一种简单的方式解决了我的问题 :-) 假设我从 doInBackground 上的 asynctask 调用的查询是这样的:

...
@Override
protected Boolean doInBackground(String... aurl) {
    Cursor newCursor = getALLmyData();
    runOnUiThread(new Runnable() {
        @Override
        public void run() {
            final Cursor oldCursor = adapter.swapCursor(newCursor);
            if(oldCursor!=null){
            oldCursor.close();
        }
    }
    });
    ....

private Cursor getALLmyData() {
    SQLiteDatabase db = this.getReadableDatabase();
    String query = "select * FORM MY_HUGE_TABLE";
    return db.rawQuery(query, null, null);
}

在这种情况下, adapter.swapCursor(newCursor); 由于适配器中的 .getCount() 方法,将阻止 UI 几秒钟。我所做的就像我以这种方式简单地更改查询一样简单

public Cursor getALLmyData() {
    SQLiteDatabase db = this.getReadableDatabase();
    String query = "select * FORM MY_HUGE_TABLE";
    Cursor res = db.rawQuery(query, null, null);
    Log.d(TAG," Rows:" +res.getCount());
    return res;
}

这样,在调用 swapCursor(newCursor) 时,完整的查询在 doInBackground 而不是主 UI 中执行,因为 res.getCount() 执行此操作 :-) 现在交换速度非常快!请注意 swapaCursor 返回适配器中的 oldCursor 并且您必须关闭它!希望能帮助到你!

于 2017-08-25T11:57:54.073 回答