我正在寻找一个加速更新我的纺纱机的解决方案。目前,我正在使用simplecursoradapter,并在基于先前选择的微调器更改搜索条件时调用changecursor。
我做了一些计时测试,查询时间从5毫秒到60毫秒,而changecursor函数需要600毫秒到4000毫秒以上。有没有另一种更新适配器上光标的方法更快?我不使用同一个查询,因此不能简单地重新查询游标,然后调用notifydatasetchanged。我必须创建一个新的查询,然后获取一个新的光标(也许有更好的方法来完成这一部分)。
以下是我目前的填充方式
private void writerSpinner() {
String[] columns = new String[] { Passage.COL_WRITER_ID + " " + BaseColumns._ID, Passage.COL_WRITER_NAME };
String whereClause = null;
String groupBy = null;
String orderBy = Passage.COL_WRITER_ID + " ASC";
if (mAdapterPassage == null) {
String[] columnsSpinner = new String[] { Passage.COL_WRITER_NAME };
int[] to = new int[] { android.R.id.text1 };
mAdapterPassage = new SimpleCursorAdapter(getActivity(), android.R.layout.simple_spinner_item, null, columnsSpinner, to);
mAdapterPassage.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
mPassage.setAdapter(mAdapterPassage);
mPassage.setOnItemSelectedListener(onItemSelectedListener);
}
AsyncLoadData loadData = new AsyncLoadData(mAdapterPassage, mPassage, Passage.TABLE_NAME_WRITERS, columns, whereClause, groupBy, orderBy);
loadData.execute();
}
private void updateChapterSpinner() {
String[] columns = new String[] { Passage.COL_WRITER_ID + " " + BaseColumns._ID, Passage.COL_CHAPTER_ID };
String whereClause = Passage.COL_WRITER_ID + " = " + mSelectedWriterId;
String groupBy = Passage.COL_CHAPTER_ID;
String orderBy = Passage.COL_CHAPTER_ID + " ASC";
if (mAdapterChapter == null) {
String[] columnsSpinner = new String[] { Passage.COL_CHAPTER_ID };
int[] to = new int[] { android.R.id.text1 };
mAdapterChapter = new SimpleCursorAdapter(getActivity(), android.R.layout.simple_spinner_item, null, columnsSpinner, to);
mAdapterChapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
mChapter.setAdapter(mAdapterChapter);
mChapter.setOnItemSelectedListener(onItemSelectedListener);
}
AsyncLoadData loadData = new AsyncLoadData(mAdapterChapter, mChapter, Passage.TABLE_NAME_PASSAGES, columns, whereClause, groupBy, orderBy);
loadData.execute();
}
private void updateVerseSpinner() {
String[] columns = new String[] { Passage.COL_WRITER_ID + " " + BaseColumns._ID, Passage.COL_VERSE_ID };
String whereClause = Passage.COL_WRITER_ID + " = " + mSelectedWriterId
+ " AND " + Passage.COL_CHAPTER_ID + " = " + mSelectedChapter;
String groupBy = Passage.COL_VERSE_ID;
String orderBy = Passage.COL_VERSE_ID + " ASC";
if (mAdapterVerse == null) {
String[] columnsSpinner = new String[] { Passage.COL_VERSE_ID };
int[] to = new int[] { android.R.id.text1 };
mAdapterVerse = new SimpleCursorAdapter(getActivity(), android.R.layout.simple_spinner_item, null, columnsSpinner, to);
mAdapterVerse.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
mVerse.setAdapter(mAdapterVerse);
mVerse.setOnItemSelectedListener(onItemSelectedListener);
}
AsyncLoadData loadData = new AsyncLoadData(mAdapterVerse, mVerse, Passage.TABLE_NAME_PASSAGES, columns, whereClause, groupBy, orderBy);
loadData.execute();
}
private class AsyncLoadData extends AsyncTask<Void, Void, Void> {
String mTableName;
String[] mColumns;
String mWhereClause;
String mGroupBy;
String mOrderBy;
Spinner mSpinner;
Cursor mCursor;
SimpleCursorAdapter mAdapter;
public AsyncLoadData(SimpleCursorAdapter adapter, Spinner spinner, String tableName, String[] columns, String whereClause, String groupBy, String orderBy) {
mAdapter = adapter;
mSpinner = spinner;
mTableName = tableName;
mColumns = columns;
mWhereClause = whereClause;
mGroupBy = groupBy;
mOrderBy = orderBy;
}
@Override
protected void onPreExecute()
{
//mSpinner.setVisibility(View.GONE);
}
@Override
protected Void doInBackground(Void... arg0) {
long startCursor = new Date().getTime();
mCursor = mDBHandler.query(mTableName, mColumns, mWhereClause, null, mGroupBy, null, mOrderBy);
long timeToQuery = new Date().getTime() - startCursor;
Log.i("CursorQuery", "Time to Query Cursor " + mGroupBy + ": " + timeToQuery + "ms");
return null;
}
@Override
protected void onPostExecute(Void result)
{
long startAdapter = new Date().getTime();
mAdapter.changeCursor(mCursor);
long timeToChangeCursor = new Date().getTime() - startAdapter;
Log.i("AdapterQuery", "Time to Change Cursor " + mGroupBy + ": " + timeToChangeCursor + "ms");
mAdapter.notifyDataSetChanged();
//mSpinner.setVisibility(View.VISIBLE);
}
}
private OnItemSelectedListener onItemSelectedListener = new OnItemSelectedListener() {
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
switch(parent.getId()) {
case R.id.bible_passage:
mSelectedWriterId = position + 1;
updateChapterSpinner();
break;
case R.id.bible_chapter:
mSelectedChapter = position + 1;
updateVerseSpinner();
break;
case R.id.bible_verse:
mSelectedVerse = position + 1;
break;
}
}
public void onNothingSelected(AdapterView<?> parent) {
}
};
最佳答案
问题changeCursor
花费如此长时间的原因是Database.query(...)
仅在必要时初始化(因此
光标的错误,而不是适配器的错误)。
游标初始化速度慢的原因是它解析
一次完成整个结果集(因为它需要知道总数)。
即使SQLite很快地返回巨大的查询,Java也非常慢。
解析它们(比sqlite慢100到1000倍)。
解决方案
进来,HugeSQLiteCursor(with JavaDoc!)。
我写这个光标是为了解决这个问题。它加载结果
增量地自动地,而不是一下子(用一个聪明的
找到总计数的方法,开销几乎为0)。
Download the .jar
file
将其添加到libs/
文件夹中,然后执行如下操作
使用它(完全限定名为com.malabarba.hugesqlitecursor.HugeSQLiteCursor
):
adapter.changeCursor(new HugeSQLiteCursor(db, stepSize,
table, columnFields,
selection, selectionArgs));
如您所见,由于结果加载缓慢,您需要
将数据库和查询参数传递给构造函数。
一旦创建,光标应该在任何情况下都能正常工作
以前使用的是sqlitecursor。
第二个参数(
stepSize
)是您想要的项目数在创建光标时初始加载。这是最重要的
参数。
整个光标的初始化时间实际上是
就像只有
stepSize
结果一样。但不要使stepSize
小于一个屏幕上的结果数。这个光标有效地消除了“Java太慢”的瓶颈。
在我的nexus 4上,它在不到60毫秒的时间内返回50.000个结果的查询,而sqlitecursor则需要大约1000毫秒。
当然,如果您的查询非常庞大,甚至sqlite返回结果的速度也很慢,那么这个游标只能让您到达目前为止。