Я сталкиваюсь с IllegalStateException, обновляющим базовый Список к Адаптеру (мог бы быть ArrayAdapter или расширение BaseAdapter, я не помню). Я не имею или помню текст исключения в данный момент, но это говорит что-то эффекту содержания Списка, изменяющегося без Адаптера, уведомленного относительно изменения.
Этот Список/may/быть обновленным от другого потока кроме (основного) потока UI. После того, как я обновлю этот список (добавляющий объект), я называю notifyDataSetChanged. Проблема, кажется, что Адаптер или ListView, подключенный к Адаптеру, пытается обновить себя, прежде чем этот метод будет вызван. Когда это происходит, IllegalStateException брошен.
Если я установил видимость ListView на УВЕДЕННЫЙ перед обновлением, то ВИДИМЫЙ снова, никакая ошибка не происходит. Но это не всегда практично.
Я считал где-нибудь, что Вы не можете изменить лежание в основе этого от другого потока - это, казалось бы, ограничило бы шаблон MVC, как с этим конкретным Списком, я хочу добавить объекты от различных потоков. Я предположил, что, пока назвал notifyDataSetChanged (), я буду в безопасности - что Адаптер не пересмотрел базовый Список, пока этот метод не был вызван, но это, кажется, не имеет место.
Я предполагаю то, что я спрашиваю, может быть безопасно обновить базовый Список от потоков кроме UI? Кроме того, если я хочу изменить данные в Адаптере, сделайте я изменяю базовый Список или сам Адаптер (через добавлять (), и т.д. методы). Изменение данных через Адаптер кажется неправильным.
Я столкнулся с потоком на другом сайте от кого-то, у кого, кажется, есть подобная проблема к моему: http://osdir.com/ml/Android-Developers/2010-04/msg01199.html (это от того, где я захватил Видимость. УВЕДЕННАЯ и.VISIBLE идея).
Чтобы дать Вам лучшее представление о моей конкретной проблеме, я опишу немного, как мой Список, Адаптер, и т.д. настраивается.
У меня есть объект под названием Очередь, которая содержит LinkedList. Очередь расширяется Заметный, и когда вещи добавляются к ее внутреннему списку через ее методы, я называю setChanged () и notifyListeners (). Этому Объекту очереди можно было добавить объекты или удаленный из любого количества потоков.
У меня есть единственное "Действие" представления очереди, которое содержит Адаптер. Это Действие, в его onCreate () метод, регистрирует слушателя Наблюдателя моего Объекта очереди. В обновлении The Observer () метод я называю notifyDataSetChanged () на Адаптере.
Я добавил большой вывод журнала и решил что, когда этот IllegalStateExcption происходит, что мой обратный вызов Наблюдателя никогда не вызывался. Таким образом, это - как будто Адаптер заметил изменение Списка, прежде чем The Observer имела шанс уведомить его Наблюдателей и назвать мой метод, чтобы уведомить Адаптер, что содержание изменилось.
Таким образом, я предполагаю то, что я спрашиваю, действительно ли это - хороший способ подстроить Адаптер? Действительно ли это - проблема, потому что я обновляю содержание Адаптера от потока кроме потока UI? Если это верно, я могу иметь решение в виду (дайте Объекту очереди Обработчик потоку UI, когда это создается, и сделайте все модификации Списка с помощью того Обработчика, но это кажется неподходящим).
Я понимаю, что это - очень открытое сообщение, но я немного потерян на этом и ценил бы любые комментарии, что я записал.
Этот список / может / обновляться из другого потока, отличного от потока пользовательского интерфейса (основного)
Это не сработает.
Я где-то читал, что вы не можете изменить лежащий в основе this из другого потока - похоже, это ограничивает шаблон MVC, как с этим конкретный список, я хочу добавить элементы из разных потоков
MVC не имеет ничего общего с потоками.
Можно ли безопасно обновить базовый список из потоков, отличных от пользовательского интерфейса?
Нет. Другие потоки могут запускать обновления адаптера (например, через post ()
), но сами обновления должны обрабатываться в основном потоке приложения для адаптера, который в настоящее время подключен к ListView
.
Кроме того, если я хочу изменить данные в адаптере, нужно ли мне изменять базовый список или сам адаптер (с помощью его add () и т. Д. методы). Изменение данных через адаптер кажется неправильным.
Вы изменяете свой адаптер
с помощью самого адаптера
для ArrayAdapter
. Вы изменяете свой адаптер
через базовую базу данных / поставщика контента для CursorAdapter
. Другие адаптеры могут отличаться.
У меня есть объект с именем Queue, который содержит LinkedList. Очередь расширяет Observable, и когда что-то добавляется в его внутренний список с помощью его методов , я вызываю setChanged () и notifyListeners ().
Рассматривали ли вы использование LinkedBlockingQueue
вместо реализации собственной потокобезопасной очереди
?
Это действие в своем методе onCreate () регистрирует прослушиватель Observer моего объекта Queue.В методе обновления () наблюдателя я вызываю notifyDataSetChanged () на адаптере.
Адаптеры
должны вызывать notifyDataSetChanged ()
для себя (если изменение вносится ими) или вызывать его у объекта, который изменяет данные (например, Курсор
для CursorAdapter
). Это MVC. Действие
не должно знать и не заботиться об изменении вашей модели данных.
Это как если бы Адаптер заметил изменение списка до того, как Наблюдатель получил возможность уведомить своих Наблюдателей, и вызвал мой метод, чтобы уведомить Адаптер {{1 }} что содержимое было изменено.
Возможно, вы используете ArrayAdapter
, и в этом случае вам мешают все эти лишние наблюдатели / уведомления, поскольку это делается за вас. Вам просто нужно организовать обновление ArrayAdapter
в основном потоке приложения.
Полагаю, я спрашиваю, это хороший способ установить Адаптер?
Не особо, ИМХО.
Это проблема, потому что я обновляю содержимое адаптера из потока , отличного от потока пользовательского интерфейса?
Если вы не принудительно запускаете обновления в основном приложении thread, это в конечном итоге приведет к сбою, как только вы решите другие проблемы.
дать объекту Queue обработчик для потока пользовательского интерфейса при его создании и внести все изменения в список с помощью этого обработчика , но это кажется неправильным.
Вы могли используйте обработчик
или вызовите post ()
в прикрепленном ListView
.
Не торопясь, я бы создал подкласс ArrayAdapter
с именем ThreadSafeArrayAdapter
и использовал бы его вместо Queue
. ThreadSafeArrayAdapter
заменяет add ()
, insert ()
и remove ()
на те, у которых суперкласс выполняет свою работу в основном поток приложения через обработчик
или post ()
.