Android listview с обновлениями датчика в реальном времени

Я работаю над приложением, которое показывает некоторые места в списке. В каждом элементе списка есть стрелка, указывающая на место (отель, бар и т. д.).

Проблема в том, что я не знаю, как эффективно обновлять эту стрелку, без локального кэширования просмотров (что, согласно видео Google I/O, я никогда не должен делать).

Стрелка должна обновляться при каждом событии датчика ориентации телефона, что происходит много раз в секунду.

Итак, есть ли лучший подход, чем вызов notifyDataSetChanged() для каждого события и повторное заполнение данных каждого элемента списка?

ОБНОВЛЕНИЕ (для @dharan и всех, кто заинтересован):

Я прекратил работу над этим проектом, потому что теперь у меня есть работа на полную ставку, но я придумал решение (нереализованное/непроверенное).

Сначала ограничьте угол поворота фиксированным шагом (например: 5, 10, 15, 20, ... 355, 360), затем кэшируйте повернутое изображение для каждого угла поворота, чтобы избежать дорогостоящих вычислений поворота изображения (но при более высокая стоимость памяти).

После этого я заставлю свой метод getView() знать, когда обновлять только изображение, а не все данные. В моем случае это так же просто, как:

public View getView(int position, View convertView, ViewGroup parent) {
     if (convertView != null && place[position].id == (Integer)convertView.getTag()){
         //the place information is already set correctly so just update the image
     }
     ...
}

После этих изменений я считаю, что вызов notifyDataSetChanged() не должен вызывать серьезных проблем с производительностью.


person bughi    schedule 19.05.2012    source источник
comment
Чтобы обновить View из строки в ListView, вы должны использовать notifyDataSetChanged(), поэтому у вас нет альтернатив. Часть про ListView + вызов notifyDataSetChanged много раз в секунду звучит не очень хорошо.   -  person user    schedule 19.05.2012


Ответы (1)


Если у вас не слишком много элементов в ListView, вы можете преобразовать их в обычный LinearLayout и управлять этими элементами по отдельности. Однако проблема с LinearLayout заключается в том, что если элемент меняет свой размер, то все (то есть все дочерние элементы) должны быть переданы. Таким образом, изменение одного элемента может вызвать повторный запуск других вещей в макете. Теперь, поскольку вы меняете стрелку компаса, вы можете обойти ее, потому что это не должно приводить к изменению общего размера каждой строки. Вам просто нужно перекрасить этот предмет.

Другой вариант - написать свой собственный макет, который использует некоторые короткие пути, делая некоторые предположения, которые не могут сделать менеджеры макетов общего назначения. Последнее, на что я мог бы обратить внимание, это то, что notifyDataSetChanged() делает скрыто. Возможно, вы сможете расширить ListView и написать метод, который перерисовывает только измененную строку (конечно, это предполагает, что высота строки не изменилась). Если высота строки изменяется, то все, что находится после этой строки, должно быть передано.

person chubbsondubs    schedule 28.05.2012
comment
Спасибо за ваши предложения, у меня будет много элементов, поэтому я не думаю, что мне следует использовать LinearLayout. Я немного почитал и наткнулся на идею использования BaseAdapter вместо ArrayAdapter, могу ли я внести свой вклад в это? Часть, которую я не жду, — это реализация интерфейсов ListAdapter и Adapter. также +1 - person bughi; 29.05.2012
comment
о, и высота строки никогда не изменится, потому что мне просто нужно повернуть изображение внутри ImageView с фиксированными размерами, все остальное остается прежним. - person bughi; 29.05.2012
comment
Правильно. Если вы продолжите использовать ListView, вы захотите создать подкласс BaseAdapter. Не так уж сложно создать подкласс. Более сложной частью будет реализация необходимого вам быстрого процесса обновления. Если вы можете получить доступ к экземпляру для строки, которую хотите обновить, вызовите для нее invalidate(), которая должна перерисовать ее без повторного выполнения макета. - person chubbsondubs; 29.05.2012
comment
Если подумать, вы можете просто попробовать использовать старый добрый метод notifyDataSetChanged(). В настоящее время я работаю над созданием музыкального приложения, и у меня есть места в моем приложении, где в списке я показываю загрузку или воспроизведение музыки с помощью notifyDataSetChanged() для обновления пользовательского интерфейса, и оно работает хорошо. Теперь я не обновляю чаще, чем, скажем, 1 секунду, но это дает вам довольно хорошую обратную связь, давая процессору отдохнуть. Я бы попробовал это, прежде чем идти по более сложному пути перерисовки каждого элемента по отдельности. - person chubbsondubs; 29.05.2012
comment
Возможно, вы правы, преждевременная оптимизация — корень всех зол, я отмечу вид с позицией в адаптере, который он в данный момент отображает, я узнаю, когда остальные представления показывают правильную информацию, и только перерисую свою стрелку - person bughi; 31.05.2012
comment
@bughi, не могли бы вы опубликовать решение для этого, я тоже пытаюсь сделать то же самое, но у меня проблемы с вращением датчика. Спасибо. - person dharan; 05.09.2012
comment
@bughi Спасибо за ваш ответ. Сначала я загружаю представление списка с расчетом пеленга между текущим и пунктом назначения и поворотом изображения на основе угла пеленга, после чего мне нужно обновить представление списка в зависимости от ориентации устройства. Можете ли вы сказать мне, что вы сделали для регулировки подшипника в соответствии с ориентацией. Спасибо - person dharan; 06.09.2012