Фильтрация Android ListView с использованием AsyncTask

У меня есть две конкурирующие проблемы.

Ситуация

Получил Massive Listview 10 000 элементов, которые я пытаюсь отфильтровать с помощью EditText при изменении.

Ошибка 1

ошибка ANR keyDispatchingTimedOut

У меня была операция фильтрации в потоке пользовательского интерфейса (что в то время казалось разумным), и я предполагаю, что это вызывает ошибку на некоторых телефонах...

Попытка исправить ошибку 1

Создал AsyncTask специально для вызова моей функции фильтра...

    /// <summary>
    /// Implementation of Android AsyncTask to perform the StudentFiltering in background
    /// </summary>
    internal class FilterStudentsTask : AsyncTask
    {
        private Student[] _students;
        private StudentList _outer;
        private StudentListAdapter _adapter;
        private string _filterText;

        public FilterStudentsTask(StudentList outer, StudentListAdapter adapter, string filterText)
        {
            this._outer = outer;
            this._adapter = adapter;
            this._filterText = filterText;
        }

        protected override Java.Lang.Object DoInBackground(params Java.Lang.Object[] @params)
        {
            // filter the list
            this._adapter.filterStudents(this._filterText);
            return true;
        }

        protected override void OnPostExecute(Java.Lang.Object result)
        {
            // Notify adapter of Data Change (to trigger re-draw)
            this._adapter.NotifyDataSetChanged();
            base.OnPostExecute(result);
        }
    }

Ошибка 2

Так что теперь, поскольку у меня есть другой поток, отвечающий за фильтрацию, он не говорит мне, что я не должен использовать фоновые потоки для этого типа операций, и это должно происходить только в потоке пользовательского интерфейса..????

E/AndroidRuntime( 9738): FATAL EXCEPTION: main
E/AndroidRuntime( 9738): java.lang.IllegalStateException: The content of the adapter has changed but ListView did not receive a notification. Make sur
e the content of your adapter is not modified from a background thread, but only from the UI thread. [in ListView(2131361885, class mapdroid.ColorFade
ListView) with Adapter(class mapdroid.StudentList_StudentListAdapter)]
E/AndroidRuntime( 9738):        at android.widget.ListView.layoutChildren(ListView.java:1510)
E/AndroidRuntime( 9738):        at android.widget.AbsListView.onLayout(AbsListView.java:1260)
E/AndroidRuntime( 9738):        at android.view.View.layout(View.java:7175)
E/AndroidRuntime( 9738):        at android.widget.RelativeLayout.onLayout(RelativeLayout.java:912)
E/AndroidRuntime( 9738):        at android.view.View.layout(View.java:7175)
E/AndroidRuntime( 9738):        at android.widget.FrameLayout.onLayout(FrameLayout.java:338)
E/AndroidRuntime( 9738):        at android.view.View.layout(View.java:7175)
E/AndroidRuntime( 9738):        at android.widget.FrameLayout.onLayout(FrameLayout.java:338)
E/AndroidRuntime( 9738):        at android.view.View.layout(View.java:7175)
E/AndroidRuntime( 9738):        at android.view.ViewRoot.performTraversals(ViewRoot.java:1140)
E/AndroidRuntime( 9738):        at android.view.ViewRoot.handleMessage(ViewRoot.java:1859)
E/AndroidRuntime( 9738):        at android.os.Handler.dispatchMessage(Handler.java:99)
E/AndroidRuntime( 9738):        at android.os.Looper.loop(Looper.java:130)
E/AndroidRuntime( 9738):        at android.app.ActivityThread.main(ActivityThread.java:3683)
E/AndroidRuntime( 9738):        at java.lang.reflect.Method.invokeNative(Native Method)
E/AndroidRuntime( 9738):        at java.lang.reflect.Method.invoke(Method.java:507)
E/AndroidRuntime( 9738):        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
E/AndroidRuntime( 9738):        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
E/AndroidRuntime( 9738):        at dalvik.system.NativeStart.main(Native Method)
W/ActivityManager(  111):   Force finishing activity MapDroid.MapDroid/mapdroid.StudentList
W/ActivityManager(  111): Activity pause timeout for HistoryRecord{40670aa0 MapDroid.MapDroid/mapdroid.StudentList}

Я что-то упустил, но кажется ли, что эти ошибки конфликтуют? как вы их мирите?


person jondavidjohn    schedule 16.09.2011    source источник
comment
Рассматривали ли вы, чтобы ваш анализатор XML вставлял данные в базу данных SQLite, а затем использовал CursorAdapter для привязки их к вашей ListView? Это даст вам гораздо более чистый код, отсутствие проблем с потоками и гораздо лучшую производительность.   -  person Philipp Reichart    schedule 16.09.2011


Ответы (1)


Я думаю, что проблема здесь

protected override Java.Lang.Object DoInBackground(params Java.Lang.Object[] @params)
    {
        // filter the list
        this._adapter.filterStudents(this._filterText);
        return true;
    }

Вы не можете получить доступ к классу Apapter из потока, отличного от пользовательского интерфейса. Попробуйте сделать что-то вроде этого

protected override Java.Lang.Object DoInBackground(params Java.Lang.Object[] @params)
    {
        // filter the list
        result = students.filterStudents(this._filterText);
        return true;
    }


protected override void OnPostExecute(Java.Lang.Object result)
        {
            // Notify adapter of Data Change (to trigger re-draw)
            this._adapter.SetItems(result);
            this._adapter.NotifyDataSetChanged();
            base.OnPostExecute(result);
        }
person mironych    schedule 16.09.2011