我的程序为我的GridView使用CursorAdapter,并使用AsynTask获取curosr并刷新我的视图。
在task的doinbackgroud中,我在sqlite中执行查询,并获取光标。 在task的onPostExecute中,我使用CursorAdapter.changeCursor通过新数据刷新我的视图。
但ui线程在changeCursor时被阻止,因为游标有太多关于数千行的数据。
光标不使用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.nodes类是Cursor。
当info.members有大约2000行时,它会在我的设备中阻止我的ui线程大约四秒钟。 我在工作线程中调用了cursor.getCount(),但它没有帮助。
答案 0 :(得分:1)
请参阅Using Cursor with ListView adapter for a large amount of data
使用changeCursor时,它调用Cursor.getCount() - “这会强制查询完全执行并计算结果”。
我这样做了 - 在后台线程中准备游标并获取它的长度(从db中提取数据将在这里执行):
stopManagingCursor(cursor);
cursor = dbAdapter.getData(query);
startManagingCursor(cursor);
count = cursor.getCount();
UI线程中的(onPostExecute)更改光标:
recordsAdapter.changeCursor(cursor);
在这种情况下,更改光标不会冻结UI线程。
答案 1 :(得分: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,你必须关闭它! 希望它有所帮助!