我正在寻找一个加速更新我的纺纱机的解决方案。目前,我正在使用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倍)。
解决方案
进来,HugeSQLiteCursorwith 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返回结果的速度也很慢,那么这个游标只能让您到达目前为止。

10-07 19:47