Métodos getViewTypeCount e getItemViewType de ArrayAdapter

159

Alguém com palavras simples pode me explicar o uso getViewTypeCount()e os getItemViewType()métodos de ArrayAdapter?

Eugene
fonte

Respostas:

308

Eles lidam com o caso em que você deseja diferentes tipos de exibição para diferentes linhas. Por exemplo, em um aplicativo de contatos, você pode querer que as linhas pares tenham imagens no lado esquerdo e as linhas ímpares tenham imagens no lado direito. Nesse caso, você usaria:

@Override
public int getViewTypeCount() {
    return 2;
}

@Override
public int getItemViewType(int position) {
    return position % 2;
}

A estrutura usa seu tipo de exibição para decidir quais exibições serão entregues convertViewno seu getViewmétodo . Em outras palavras, no exemplo acima, suas linhas pares só terão vistas recicladas com imagens no lado esquerdo para reutilização, e as linhas ímpares terão apenas aquelas com imagens à direita.

Se todas as linhas da sua lista tiverem o mesmo layout, não será necessário se preocupar com os tipos de exibição. De fato, BaseAdapter.java fornece um comportamento padrão para todos os adaptadores:

public int getItemViewType(int position) {
    return 0;
}

public int getViewTypeCount() {
    return 1;
}

Isso realmente fornece o mesmo tipo de exibição para cada linha.

Editar - para descrever o fluxo geral:

  1. Você liga os dados ao seu AdapterViewuso de um adaptador.
  2. As AdapterViewtentativas para exibir itens visíveis para o usuário.
  3. A estrutura solicita getItemViewTypelinha n, a linha que está prestes a exibir.
  4. A estrutura verifica seu pool de visualizações recicladas quanto a visualizações do ntipo de linha . Não encontra nenhum porque ainda não foram recicladas visualizações.
  5. getViewé chamado para linha n.
  6. Você solicita getItemViewTypeuma linha npara determinar que tipo de visualização você deve usar.
  7. Você usa uma instrução if / switch para aumentar um arquivo xml diferente, dependendo do tipo de exibição necessário.
  8. Você preenche a exibição com informações.
  9. Você retorna a exibição, saindo getView, e a exibição da sua linha é exibida para o usuário.

Agora, quando uma exibição é reciclada rolando para fora da tela, ela entra em um pool de exibições recicladas que é gerenciado pela estrutura. Eles são essencialmente organizados por tipo de visualização, de modo que uma visualização do tipo correto seja fornecida no convertViewparâmetro em seu getViewmétodo:

  1. A estrutura novamente pede getItemViewTypea linha que deseja exibir.
  2. Desta vez, há uma exibição no pool reciclado do tipo apropriado.
  3. A visualização reciclada é passada para você como o convertViewparâmetro para o seu getViewmétodo.
  4. Você preenche a exibição reciclada com novas informações e as devolve.
Matthew Willis
fonte
1
@ Matthew, obrigado pela sua resposta. Você pode descrever o fluxo como esses métodos são chamados. Também não entendo como isso está realmente associado aos meus dados em res / layout.
31911 Eugene
Não há um contrato explícito para quando esses métodos são chamados. res / layout é o local para visualizar objetos. Este é um adaptador . Você deve verificar o tipo de item no seu método getView e aumentar a exibição adequada de res / layout de acordo.
Matthew Willis
1
Você está retornando você mesmo em getItemViewType.
Matthew Willis
Você faz a associação manualmente no getView: if (tipo == 0) {/ * inflar R.layout.row_icon_on_left /} else {/ inflar R.layout.row_icon_on_right * /}
Matthew Willis
75
Cuidado! getItemViewType () deve retornar um int entre 0 e getViewTypeCount () - 1.
PacificSky 10/12/12
12

Se precisarmos mostrar um tipo diferente de exibição na exibição de lista, é bom usá-lo getViewTypeCount()e getItemViewType()no adaptador em vez de alternar uma exibição View.GONEe View.VISIBLEpode ser uma tarefa muito cara, o getView()que afetará a rolagem da lista.

Por favor, verifique este para uso do getViewTypeCount()e getItemViewType()no adaptador.

Link: o-uso-de-getviewtypecount

kyogs
fonte
O retorno de IGNORE_ITEM_VIEW_TYPE em getItemViewType () sempre passará 'view' como nulo em getView (posição int, vista de exibição, ViewGroup viewGroup) forçando a inicializar todos os componentes da interface do usuário. Não é um indicador de desempenho ruim, no qual, no caso de um padrão de suporte, podemos reutilizar as visualizações existentes da interface do usuário e podemos simplesmente alternar a visualização para View.GONE ou View.VISIBLE com base na posição.
Namrata Bagerwal
11

Assista Outttt !!!!
Eu tive que enfrentar um problema ao implementar um ListViewontem e há dois tipos de visualizações de linhas desordenadas logo após eu rolar. Embora a resposta mais votada neste tópico dê uma boa explicação geral, ela não destacou a parte mais importante das informações para interromper o bug da interface do usuário acima mencionado.

Aqui é a minha explicação:
Ambos getViewTypeCount()e getItemViewType()estão sendo usados por BaseAdapter's getViewmétodo para descobrir qual o tipo de uma visão deve-se buscar, reciclados e devolvidos. (conforme explicado na resposta superior no tópico). Mas se você não implementar esses dois métodos de maneira intuitiva, de acordo com o Android API Doc, poderá entrar no problema que mencionei.

Resumido Orientação para a implementação:
Para implementar vários tipos de Viewspara ListViewlinhas 's temos de implementar, essencialmente, getItemViewType()e getViewTypeCount()métodos. E a getItemViewType()documentação nos fornece uma nota da seguinte maneira:

Nota: Os números inteiros devem estar no intervalo 0de getViewTypeCount() - 1. IGNORE_ITEM_VIEW_TYPEtambém pode ser devolvido.

Portanto, getItemViewType()você deve retornar valores para o Tipo de exibição, começando em 0, para o último tipo como (número de tipos - 1). Por exemplo, digamos que você tenha apenas três tipos de visualizações? Portanto, dependendo do objeto de dados da exibição, você pode retornar apenas 0 ou 1 ou 2 do getItemViewType()método, como um índice de matriz baseado em zero. E como você tem três tipos de visualizações usadas, seu getViewTypeCount()método deve retornar 3.

De qualquer forma, se você retornar outros valores inteiros como 1, 2, 3 ou 111, 222, 333 para esse método, você definitivamente poderá experimentar o bug da interface do usuário acima, que acabou de colocar, não obedecendo ao Documento da API do Android.

Se você não recebeu a pista ou ainda não conseguiu resolver e precisa de mais informações, leia minha resposta detalhada neste tópico de perguntas e respostas do StackOverflow .

Leia o Documento do desenvolvedor do Android para obter mais informações. Você pode encontrar a pista diretamente.

Espero que esta resposta possa ser útil para alguém lá fora, para economizar muitas horas !!!

Felicidades!!!

Randika Vishman
fonte
1
Obrigado por mencionar IGNORE_ITEM_VIEW_TYPEque tive um bug em um dos meus ListView. Usei um ArrayAdapter para inserir uma visualização composta por 1 imagem e 2 de texto. Eu tinha apenas um tipo de visualização. Tentei não substituir o método getItemViewType ou substituí-lo retornando a posição ou um número inteiro codificado. Em todos os casos, eu estava enfrentando duplicatas na minha lista, com um comportamento estranho ao rolar (alterações nas duplicatas). O retorno IGNORE_ITEM_VIEW_TYPEdo método corrigiu o problema. Obrigado.
Alex
@ Alex feliz por ter sido útil para você! :-)
Randika Vishman