Android - создайте очень большой ListView на основе курсора SQL

1

У меня есть запрос SQLite, возвращающий тысячи строк, которые я хочу визуализировать с помощью ListView.

Чтобы поддерживать поток пользовательского интерфейса, я создаю ListAdapter в фоновом потоке.

Однако оператор, который занимает больше времени (и может вызвать ANR), является ListActivity.setListAdapter, который я должен выполнить в потоке пользовательского интерфейса... Любые советы?

public class CursorTestActivity extends ListActivity {

    private static final String LOGTAG = "DBTEST";

    private DatabaseManager mDbManager;
    private Cursor mCursor;
    private HandlerThread mIOWorkerThread;
    private Handler mIOHandler;
    private Handler mUIHandler;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        mDbManager = new DatabaseManager(this);

        mUIHandler = new Handler();
        createIOWorkerThread();

        log("creating cursor");
        mCursor = mDbManager.getCursor(); // does db.query(...)
        startManagingCursor(mCursor);

        mIOHandler.post(new Runnable() {
            @Override
            public void run() {
                setMyListAdapter();
            }
        });
        log("onCreate done");
    }

    private void setMyListAdapter() {
        log("constructing adapter");
        // CustomCursorAdapter implements bindView and newView
        final CustomCursorAdapter listAdapter = new CustomCursorAdapter(this,
                mCursor, false);
        log("finished constructing adapter");
        mUIHandler.post(new Runnable() {
            @Override
            public void run() {
                log("setting list adapter");
                setListAdapter(listAdapter); // gets slower the more rows are returned
                log("setting content view");
                setContentView(R.layout.main);
                log("done setting content view");
            }
        });
    }

    private void createIOWorkerThread() {
        mIOWorkerThread = new HandlerThread("io_thread");
        mIOWorkerThread.start();
        Looper looper = mIOWorkerThread.getLooper();
        mIOHandler = new Handler(looper);
    }

    private void destroyIOWorkerThread() {
        if (mIOWorkerThread == null)
            return;
        Looper looper = mIOWorkerThread.getLooper();
        if (looper != null) {
            looper.quit();
        }
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        if (mDbManager != null)
            mDbManager.close();
        destroyIOWorkerThread();
    }

    private static void log(String s) {
        Log.d(LOGTAG, s);
    }

}
Теги:
android-recyclerview
listview
cursor

1 ответ

0

Курсоры ленивы загружаются, поэтому при первом доступе к данным курсор загружается - getCount - это такой доступ. Метод setAdapter вызывает getCount на курсоре - проблема с производительностью.

  • Вы можете установить пустой курсор в адаптере и отобразить пустой список во время загрузки курсора. Затем используйте changeCursor метод в адаптере, чтобы изменить курсор на новый.
  • Сначала вы можете получить сначала 100 строк в первом запросе, затем загрузите больше строк в фоновом режиме и измените курсор на новый.
  • Или вы можете создать собственную реализацию Cursor, которая имеет собственную реализацию getCount и запрашивает требуемые строки по запросу.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню