Pergunta

Este é um cenário muito comum:. Exibir imagens em um ListView que tem que ser baixado da internet

Agora eu tenho uma subclasse personalizada de ArrayAdapter que eu uso para o ListView. Na minha aplicação getView () do ArrayAdapter, eu gerar um segmento separado para carregar uma imagem. Após o carregamento é feito, ele procura o ImageView apropriado e define a imagem com ImageView.setImageDrawable (). Portanto, a solução que eu usei é tipo de semelhante a este: carga preguiçoso de imagens em ListView

O problema que estou tendo é que, assim como eu fazer a chamada para setImageDrawable () no ImageView, o ListView de alguma forma Atualiza todas as fileiras atualmente visíveis na lista! Isso resulta em uma espécie de loop infinito:

  1. getView () é chamado
  2. thread é gerado imagem carga
  3. imagem é carregada; setImageDrawable () é chamado em ImageView
  4. ListView pega por algum motivo e refresca-se
  5. Para o ListView para atualizar, getView () é chamado para cada linha visível, então, voltamos para a etapa 1 ea coisa toda se repete

Assim, tanto quanto eu posso ver, a solução proposta em "Android - Como eu faço uma carga lenta de imagens em ListView" (ver link acima) simplesmente não funciona. Pode parecer que faz, mas ele será executado muito lento, porque no fundo, ele mantém recarregar as fileiras atualmente visíveis.

Alguém encontro isso antes e / ou ter uma solução para isso?

Foi útil?

Solução

Na solução ligada, fetchDrawableOnThread() só deve ser chamado se a vista já não tem o drawable correta.

Uma visão não tem um drawable se getDrawable() retorna null.

Se você estiver reutilizando slots, você vê que você precisa para ir mais longe e gerenciar o estado. Se os seus pontos de vista tem uma variável de membro armazenar a URL, e um booleano para dizer se ele é carregado, seria fácil saber se a fetchDrawableOnThread() chamada ou não, por exemplo.

Eu especulam que toString() do drawable detalhou o caminho a partir do qual a imagem foi carregada. (Se isso não acontecer, você poderia subclasse o drawable voltou a fazê-lo assim). Neste caso, você poderia evitar o boolean descrito acima e apenas fazer uma comparação para determinar se a sua drawable direita ou se deve buscar um substituto.

Além disso, seu getView () em uma linha visível deve garantir que aqueles que não get mais visível descarregado, para evitar a exaustão de memória. A finesse seria mover as imagens não mais visível para referências macios (assim eles são descarregados quando é necessária memória) como outro cartaz sobre o segmento original observou.

Outras dicas

Eu usei o código no seguinte link: outra pergunta stackoverflow

i feitas pequenas alterações a fim de resolver a reciclagem de vista problem.I definir a url da imagem para Tag de ImageView no adaptador. Seguinte código contém a minha solução que resolve a reciclagem problema:

public void fetchDrawableOnThread(final String urlString, final ImageView imageView,Drawable drw) {

    imageView.setImageDrawable(drw);//drw is default image
    if (drawableMap.containsKey(urlString)) {
        if(imageView.getTag().toString().equals(urlString))
        {
            imageView.setImageBitmap(drawableMap.get(urlString));
            imageView.invalidate();
            return;
        }

    }

    final Handler handler = new Handler() {
        @Override
        public void handleMessage(Message message) {
            BitmapWrapper wrapper = (BitmapWrapper)message.obj;
            if(wrapper.imageurl.equals(imageView.getTag().toString()))
            {
                imageView.setImageBitmap((Bitmap)wrapper.bitmap);
                imageView.invalidate();
            }

        }
    };

    Thread thread = new Thread() {
        @Override
        public void run() {
            //TODO : set imageView to a "pending" image

            Bitmap drawable = fetchDrawable(urlString);
            BitmapWrapper wrapper = new BitmapWrapper();
            wrapper.bitmap = drawable;
            wrapper.imageurl = urlString;
            Message message = handler.obtainMessage(1, wrapper);
            handler.sendMessage(message);
        }
    };
    thread.start();
}


    public class BitmapWrapper
{
    public Bitmap bitmap;
    public String imageurl;
}

Eu tive o mesmo problema.

Depois de quase 2 dias de depuração heavy / otimização e tentando descobrir, porque meu getView() é chamado para todas as vistas e outra vez quando se utiliza setImageBitmap() em uma fileira, eu vim com uma solução suja:

1) Estender a ImageView costume que você usa para todas as imagens em sua lista

2) neste ImageView sobrescrever o método

@Override
public void requestLayout()
{ 
  return; 
}

3) Dirty, mas para mim ele funciona

4) Lucro;)

Eu tenho um ThumbnailAdapter que embrulha-se todo este padrão que ajuda Maio.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top