Състезание с LoaderManager?

Използвам LoaderManager, за да заредя курсор на списък с контакти от моя телефон.

Използвам буквално само примерния код, даден тук:

http://developer.android.com/reference/android/app/LoaderManager.html

Единствената ми промяна е, че вместо да използвам това като адаптер за изглед на списък на главния екран, аз го използвах като адаптер за AutoCompleteTextView. Проблемът ми е, че когато бързо променя текста, или като пиша яростно, или като задържам бутона за изтриване, за да изтрия всичко подред, това води до тази грешка:

01-09 02:36:47.248: E/AndroidRuntime(24231): FATAL EXCEPTION: main
01-09 02:36:47.248: E/AndroidRuntime(24231): android.database.StaleDataException: Attempted to access a cursor after it has been closed.
01-09 02:36:47.248: E/AndroidRuntime(24231):    at android.database.BulkCursorToCursorAdaptor.throwIfCursorIsClosed(BulkCursorToCursorAdaptor.java:64)
01-09 02:36:47.248: E/AndroidRuntime(24231):    at android.database.BulkCursorToCursorAdaptor.getColumnNames(BulkCursorToCursorAdaptor.java:159)
01-09 02:36:47.248: E/AndroidRuntime(24231):    at android.database.AbstractCursor.getColumnIndex(AbstractCursor.java:283)
01-09 02:36:47.248: E/AndroidRuntime(24231):    at android.database.AbstractCursor.getColumnIndexOrThrow(AbstractCursor.java:308)
01-09 02:36:47.248: E/AndroidRuntime(24231):    at android.database.CursorWrapper.getColumnIndexOrThrow(CursorWrapper.java:78)
01-09 02:36:47.248: E/AndroidRuntime(24231):    at android.widget.CursorAdapter.swapCursor(CursorAdapter.java:338)
01-09 02:36:47.248: E/AndroidRuntime(24231):    at android.widget.CursorAdapter.changeCursor(CursorAdapter.java:309)
01-09 02:36:47.248: E/AndroidRuntime(24231):    at android.widget.CursorFilter.publishResults(CursorFilter.java:67)
01-09 02:36:47.248: E/AndroidRuntime(24231):    at android.widget.Filter$ResultsHandler.handleMessage(Filter.java:282)
01-09 02:36:47.248: E/AndroidRuntime(24231):    at android.os.Handler.dispatchMessage(Handler.java:99)
01-09 02:36:47.248: E/AndroidRuntime(24231):    at android.os.Looper.loop(Looper.java:137)
01-09 02:36:47.248: E/AndroidRuntime(24231):    at android.app.ActivityThread.main(ActivityThread.java:5070)
01-09 02:36:47.248: E/AndroidRuntime(24231):    at java.lang.reflect.Method.invokeNative(Native Method)
01-09 02:36:47.248: E/AndroidRuntime(24231):    at java.lang.reflect.Method.invoke(Method.java:511)
01-09 02:36:47.248: E/AndroidRuntime(24231):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:795)
01-09 02:36:47.248: E/AndroidRuntime(24231):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:558)
01-09 02:36:47.248: E/AndroidRuntime(24231):    at dalvik.system.NativeStart.main(Native Method)

person David Liu    schedule 09.01.2013    source източник


Отговори (1)


Изглежда, че CursorAdapter има базова реализация на getFilter(), която връща текущия курсор след преминаване през runQueryOnBackgroundThread(). Това работи добре за оригиналния пример за разработчици на Android за LoaderManager, тъй като ListViews изобщо не използват филтъра. Въпреки това AutoCompleteTextViews използват филтъра, така че по същество изпълнявах две асинхронни нишки, които се опитваха да заредят курсори и не бяха безопасни за нишки.

Тъй като Filter вече предоставя същата функционалност за асинхронно зареждане, която прави LoaderManager, току-що премахнах LoaderManager и заредих през филтъра, като замених CursorAdapter.runQueryOnBackgroundThread().

person David Liu    schedule 10.01.2013
comment
За всички бъдещи търсещи отговори, LoaderManagers са смешно остарели в днешно време, така че трябва да се избягват на всяка цена. - person David Liu; 30.03.2018