Что лучшая практика путь состоит в том, чтобы обновить базовые данные Адаптера?

Я сталкиваюсь с 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, когда это создается, и сделайте все модификации Списка с помощью того Обработчика, но это кажется неподходящим).

Я понимаю, что это - очень открытое сообщение, но я немного потерян на этом и ценил бы любые комментарии, что я записал.

8
задан skyler 25 April 2010 в 06:23
поделиться

1 ответ

Этот список / может / обновляться из другого потока, отличного от потока пользовательского интерфейса (основного)

Это не сработает.

Я где-то читал, что вы не можете изменить лежащий в основе 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 () .

8
ответ дан 5 December 2019 в 20:14
поделиться
Другие вопросы по тегам:

Похожие вопросы: