exemplo notifyDataSetChanged

166

Eu estou tentando usar no meu Android Applicationo notifyDataSetChanged()método para um ArrayAdapter, mas ele não funciona para mim.

Eu encontrei como resposta aqui , que notifyDataSetChanged()deve ser executado no thread principal, mas não havia exemplo para isso.

Alguém poderia enviar um exemplo ou pelo menos um link ?!

Tima
fonte
você pode verificar este blogue e este exemplo no github e isso também
Cabezas

Respostas:

328

Para um ArrayAdapter, notifyDataSetChangedsó funciona se você usar o add(), insert(), remove(), e clear()no adaptador.

Quando um ArrayAdapteré construído, ele mantém a referência do Listque foi passado. Se você fosse passar um Listque era membro de uma Atividade e alterá-lo mais tarde, ele ArrayAdapterainda mantém uma referência ao original List. O adaptador não sabe que você alterou o Listna atividade.

Suas escolhas são:

  1. Use as funções do ArrayAdapterpara modificar a lista subjacente ( add(), insert(), remove(), clear(), etc.)
  2. Recrie o ArrayAdaptercom os novos Listdados. (Usa muitos recursos e coleta de lixo.)
  3. Crie sua própria classe derivada BaseAdaptere ListAdapterque permita a alteração da Listestrutura de dados subjacente .
  4. Use notifyDataSetChanged()sempre que a lista for atualizada. Para chamá-lo no UI-Thread, use o runOnUiThread()de Activity. Então, notifyDataSetChanged()vai funcionar.
jnosek
fonte
13
tenha cuidado também de atribuir objetos 'novos' aos seus dados. usar clear () em vez disso, repovoar / fazer alterações aos dados, em seguida, chamar notifyDataSetChanged ()
moonlightcheese
Mas e se chamarmos notifyDataSetChanged()dessa maneira ((BaseAdapter) arrayAdapter).notifyDataSetChanged();:?
TeoREtik
2
Eu uso BaseExpandableListAdapter, ele não tem funções add () ou remove (), então eu armazeno meu mapa como uma variável de membro. Eu atualizo o Map e ligo para notifyDatasetChanged (), mas nada acontece. Quando eu uso a opção nº 4, ela funciona. Por quê???
Emeraldhieu # 25/12
Estou usando ArrayAdapter para GridView personalizado, estou adicionando imagens à medida que as obtenho de URLs, chamando adapter.add (dataReceived). Isso funciona bem adiciona dados, mas por que é refrescante e vai para o topo. Quero mostrar os itens, pois eles serão adicionados sem atualizar a lista. (O que você quer fazer é trabalhar com o GridView do Android usando notifyDatasetChanged ()) Como fazê-lo funcionar neste customGridView (StaggeredGridView).
MobileEvangelist
1
Tentei criar meu próprio BaseAdapter para adicionar métodos de classificação à lista, mas por algum motivo isso simplesmente não funcionou. Não que meu aplicativo seja lento, mesmo que eu recrie todo o adaptador com uma lista de matrizes classificada, mas ainda me irrita. Como exatamente isso criaria muito lixo? Suponho que a matriz real de dados dispendiosos seja mantida como uma referência na atividade que chama o adaptador, o que significa que apenas o adaptador será coletado.
G_V
34

Você pode usar o runOnUiThread()método da seguinte maneira. Se você não estiver usando a ListActivity, basta adaptar o código para obter uma referência ao seu ArrayAdapter.

final ArrayAdapter adapter = ((ArrayAdapter)getListAdapter());
runOnUiThread(new Runnable() {
    public void run() {
        adapter.notifyDataSetChanged();
    }
});
Brian
fonte
1
Tentei adicionar o seu fragmento de código no meu código (você pode encontrá-lo aqui stackoverflow.com/questions/3667442/how-to-refresh-adapter ) no método onCreate, mas ainda não tenho sucesso :( talvez fosse lugar errado para adicioná-lo ?!
Tima
1
Sua pergunta acabou de perguntar como você poderia chamar o método e executá-lo no thread principal da interface do usuário. Isso responde a essa pergunta. No seu caso específico ( stackoverflow.com/questions/3670500/… ), o AsyncTask e seu método onPostExecute () parecem ser o que você deve considerar.
Brian
12

Eu escrevi recentemente sobre esse tópico, embora este post seja antigo, achei que seria útil para alguém que deseja saber como implementar BaseAdapter.notifyDataSetChanged()passo a passo e de maneira correta.

Siga Como implementar corretamente BaseAdapter.notifyDataSetChanged () no Android ou o blog mais recente BaseAdapter.notifyDataSetChanged () .

Arif Nadeem
fonte
Olá, eu tentei o primeiro exemplo de link, mas, em vez de mItem.add(), eu fiz apenas a edição de um elemento, mItem.get(position).setImage(encodedImage)pode ser que seja por isso que está dando a exceção de NullPointer de erro. somente para add (), clear (), remove () etc #
Shreekant N
notifyDataSetChanged funcionará para editar ou modificar o conjunto de dados, seu ponteiro nulo é por causa de outra coisa, verifique os logs.
Arif Nadeem
7

Eu tive o mesmo problema e prefiro não substituir o ArrayAdapter inteiro por uma nova instância continuamente. Portanto, eu tenho o AdapterHelper fazendo o trabalho pesado em outro lugar.

Adicione isto onde você normalmente (tentaria) ligar para notificar

new AdapterHelper().update((ArrayAdapter)adapter, new ArrayList<Object>(yourArrayList));
adapter.notifyDataSetChanged();

Classe AdapterHelper

public class AdapterHelper {
    @SuppressWarnings({ "rawtypes", "unchecked" })
    public void update(ArrayAdapter arrayAdapter, ArrayList<Object> listOfObject){
        arrayAdapter.clear();
        for (Object object : listOfObject){
            arrayAdapter.add(object);
        }
    }
}
Kevin Parker
fonte
Eu tenho alguns outros ArrayAdapters no meu código e eles funcionaram sem problemas. Hoje à noite, decidi transformar um SimpleCursorAdapter em um ArrayAdapter, e NÃO FUNCIONARIA. Depois de lutar por algumas horas e tentar encontrar um motivo pelo qual não funcionaria, encontrei sua classe AdapterHelper e AGORA AGORA FUNCIONA! Obrigado!
Proudgeekdad
1
Isso pode ser feito facilmente em uma função ... POR QUE você instanciaria uma nova classe para ela?
techiServices
2
Em Java, as funções são chamadas métodos. O que você propõe, tem esse método altamente reutilizável na mesma classe que o Array Adapter, talvez? Ou o fragmento / atividade que contém a exibição de lista? Então, sim, está em uma classe onde pode ser reutilizado. Se você quiser torná-lo estático, vá em frente.
Kevin Parker
1
Boa ideia. Outro seria estender o ArrayAdapter, chamado ArrayAdapterCompat e substituir o método addAll (..), já que este está disponível apenas desde a API 11. Lá, verifique o nível da API e use super.addAll(..)API> 11 e super.add (.. ) em combinação com iteração como a sua: if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) { super.addAll(items); } else { for (Object o : collection) { super.add(o); } }. Agora basta estender sua nova classe de adaptadores.
Konsumierer 26/10/12
Perfeito! Muito obrigado @ Kevin - era exatamente isso que eu precisava!
Kibi
3

Sei que esta é uma resposta tardia, mas estava enfrentando um problema semelhante e consegui resolvê-lo usando notifyDataSetChanged()no lugar certo.

Então, minha situação era a seguinte.

Eu tive que atualizar uma exibição de lista em uma guia da barra de ação (fragmento) com o conteúdo retornado de uma atividade completamente diferente. Inicialmente, no entanto, a exibição de lista não refletia nenhuma alteração. No entanto, ao clicar em outra guia e retornar à guia desejada, a exibição da lista seria atualizada com o conteúdo correto da outra atividade. Então, para resolver isso, usei notifyDataSetChanged()o adaptador da barra de ação no código da atividade que teve que retornar os dados.

Este é o trecho de código que eu usei na atividade.

@Override
public boolean onOptionsItemSelected(MenuItem item) {

    switch (item.getItemId()) 
    {
        case R.id.action_new_forward:

            FragmentTab2.mListAdapter.notifyDataSetChanged();//this updates the adapter in my action bar tab
            Intent ina = new Intent(getApplicationContext(), MainActivity.class);
            ina.putExtra("stra", values1);
            startActivity(ina);// This is the code to start the parent activity of my action bar tab(fragment).
    }
}

Essa atividade retornaria alguns dados FragmentTab2e atualizaria diretamente minha listview em FragmentTab2.

Espero que alguém ache isso útil!

mutp
fonte