Eu tenho um ListView
que exibe itens de notícias. Eles contêm uma imagem, um título e algum texto. A imagem é carregada em um thread separado (com uma fila e tudo) e, quando a imagem é baixada, chamo agora notifyDataSetChanged()
o adaptador de lista para atualizar a imagem. Isso funciona, mas getView()
está sendo chamado com muita frequência, pois notifyDataSetChanged()
solicita getView()
todos os itens visíveis. Quero atualizar apenas o item único na lista. Como eu faria isso?
Os problemas que tenho com minha abordagem atual são:
- A rolagem é lenta
- Tenho uma animação gradual na imagem, que acontece toda vez que uma única nova imagem da lista é carregada.
Esta pergunta foi feita no Google I / O 2010, você pode assisti-la aqui:
O mundo do ListView, hora 52:30
Basicamente o que Romain Guy explica é chamar
getChildAt(int)
aListView
obter a vista e chamada (eu acho)getFirstVisiblePosition()
para descobrir a correlação entre a posição e índice.Romain também aponta para o projeto chamado Shelves como um exemplo, acho que ele pode ser o método
ShelvesActivity.updateBookCovers()
, mas não consigo encontrar o chamadogetFirstVisiblePosition()
.ATUALIZAÇÕES IMPRESSIONANTES QUE VÊM:
O RecyclerView corrigirá isso no futuro próximo. Conforme indicado em http://www.grokkingandroid.com/first-glance-androids-recyclerview/ , você poderá chamar métodos para especificar exatamente a alteração, como:
Além disso, todos desejarão usar as novas visualizações baseadas no RecyclerView, pois serão recompensadas com animações bonitas! O futuro parece incrível! :-)
fonte
Foi assim que eu fiz:
Seus itens (linhas) devem ter IDs exclusivos para que você possa atualizá-los mais tarde. Defina a tag de todas as visualizações quando a lista estiver obtendo a visualização do adaptador. (Você também pode usar a tag key se a tag padrão for usada em outro lugar)
Para a atualização, verifique todos os elementos da lista, se uma visualização com o ID fornecido estiver visível, para que possamos executar a atualização.
Na verdade, é mais fácil do que outros métodos e melhor quando você lida com identificações e não posições! Além disso, você deve chamar a atualização para itens que ficam visíveis.
fonte
obtenha a classe de modelo primeiro como global como este objeto de classe de modelo
e inicializá-lo para global
obtenha a linha atual da visualização pelo modelo, inicializando-o no modelo global
defina o valor alterado para o método de objeto de modelo global a ser definido e inclua o notifyDataSetChanged que funciona para mim
Aqui está uma pergunta relacionada com boas respostas.
fonte
As respostas são claras e corretas, vou adicionar uma ideia para o
CursorAdapter
caso aqui.Se você está subclassificando
CursorAdapter
(ouResourceCursorAdapter
, ouSimpleCursorAdapter
), pode implementarViewBinder
ou substituirbindView()
enewView()
métodos, eles não recebem o índice atual do item da lista nos argumentos. Portanto, quando alguns dados chegam e você deseja atualizar itens relevantes da lista visível, como você conhece os índices deles?Minha solução alternativa foi:
newView()
notifyDatasetChanged()
e atualizar todos elesDevido à reciclagem de visualizações, o número de referências de visualização que preciso armazenar e a iteração será aproximadamente igual ao número de itens da lista visíveis na tela.
fonte
Para o RecycleView, use este código
fonte
Eu usei o código que forneceu o Erik, funciona muito bem, mas tenho um adaptador personalizado complexo para o meu listview e fui confrontado com a implementação duas vezes do código que atualiza a interface do usuário. Tentei obter a nova visualização dos meus métodos getView dos adaptadores (a arraylist que contém os dados da listview já foi atualizada / alterada):
Está funcionando bem, mas não sei se é uma boa prática. Portanto, não preciso implementar o código que atualiza o item da lista duas vezes.
fonte
exatamente eu usei isso
fonte
Criei outra solução, como o método RecyclyerView void
notifyItemChanged(int position)
, crie a classe CustomBaseAdapter da seguinte maneira:Não se esqueça de criar uma classe CustomDataSetObservable também para a
mDataSetObservable
variável CustomAdapterClass , assim:na classe CustomBaseAdapter, existe um método
notifyItemChanged(int position)
, e você pode chamá-lo quando quiser atualizar uma linha onde quiser (clique no botão ou em qualquer lugar que desejar chamar esse método). E pronto !, sua única linha será atualizada instantaneamente ..fonte
Minha solução: se estiver correto *, atualize os dados e os itens visíveis sem redesenhar a lista inteira. Caso contrário, notifyDataSetChanged.
Correto - tamanho dos dados antigos == novo tamanho dos dados e IDs de dados antigos e sua ordem == novos IDs de dados e ordem
Quão:
e claro:
Ignore o último parâmetro para bindView (eu o uso para determinar se preciso ou não reciclar bitmaps para o ImageDrawable).
Como mencionado acima, o número total de visualizações 'visíveis' é aproximadamente a quantidade que cabe na tela (ignorando as alterações de orientação, etc.), portanto, nada demais em termos de memória.
fonte
Além desta solução ( https://stackoverflow.com/a/3727813/5218712 ), basta adicionar que ela deve funcionar apenas se houver
listView.getChildCount() == yourDataList.size();
uma visualização adicional dentro do ListView.Exemplo de como os elementos filho são preenchidos:
fonte