Solucionado (ver solução)
Solucionado
(ver solução)
4
respostas

Funcionamento do AsyncTask

Olá, pessoal.

Gostaria de entender melhor o funcionamento de um método usando o AsyncTask. No atualiza abaixo, por exemplo, faço um filtro para aparecer somente as visitas cadastradas de acordo com a sua situação. Contudo, pelo log de erro, vi que estava dando NPE e coloquei o Toast para ver o que estava acontecendo. Ele realmente imprimia null e o motivo foi a declaração do array List<Visita> visitas_filtradas = new ArrayList<>(); antes do for.

public void atualiza(List<Visita> visitas) {
        List<Visita> visitas_filtradas = new ArrayList<>();
        for (int i = 0; i < visitas.size(); i++) {
            int finalI = i;
            new BuscaVisita_String_DaSituacaoTask(situacaoDAO, visitas.get(i), encontrada -> {
                if (encontrada != null) {
                    if (encontrada.equals(SITUACAO_CONTATO_ESCOLA_PARA) || encontrada.equals(SITUACAO_AMBIENTACAO_PARA)) {
                        visitas_filtradas.add(visitas.get(finalI));
                    }
                }else
                    Toast.makeText(context, encontrada, Toast.LENGTH_SHORT).show();
            }).execute();
        }
        this.visitas.clear();
        this.visitas.addAll(visitas_filtradas);
        notifyDataSetChanged();
    }

Percebi que se eu colocasse a inicialização do array fora do método, como abaixo, o Toast imprimia a situação encontrada. Ou seja, não imprimir mais o null.

public void atualiza(List<Visita> visitas) {
-------------------------------------------------- Tirei o array visitas_filtradas que estava aqui e agora deu certo
        for (int i = 0; i < visitas.size(); i++) {
            int finalI = i;
            new BuscaVisita_String_DaSituacaoTask(situacaoDAO, visitas.get(i), encontrada -> {
                if (encontrada != null) {
                    Toast.makeText(context, "Aparece: " + encontrada, Toast.LENGTH_SHORT).show();
                    if (encontrada.equals(SITUACAO_CONTATO_ESCOLA_PARA) || encontrada.equals(SITUACAO_AMBIENTACAO_PARA)) {
                        visitas_filtradas.add(visitas.get(finalI));
                    }
                }else
                    Toast.makeText(context, "Não aparece: " + encontrada, Toast.LENGTH_SHORT).show();
            }).execute();
        }
        this.visitas.clear();
        this.visitas.addAll(visitas_filtradas);
        visitas_filtradas.clear();
        notifyDataSetChanged();
    }

Deu certo em partes. O problema disso é que o array duplicava as visitas quando o método atualiza era chamado novamente. Teria que limpá-lo no início da chamada e, no código acima, o visitas_filtradas.clear(); ficou só no final.

Porém, se eu coloco visitas_filtradas.clear(); antes do for, dá NPE novamente com um NULL.

Por que isso acontece e o que fazer, por favor?

4 respostas
solução!

Oi Thiago, tudo bem?

Notei que a evolução do seu código apresentou mais de um problema e também o nome do método faz mais do que ele deveria fazer. Sendo assim, a primeira técnica que recomendo fazer é extrair comportamentos (métodos). Como por exemplo, o atualiza() deve apenas receber os dados e atualizar o dataset das visitas.

Em outras palavras, o ideal é fazer com que essa BuscaVisita_String_DaSituacaoTask seja feita em um outro lugar... Aparentemente, vc chamaria a task, e então, após ter o resultado por meio da expressão lambda, vc faz as operações que precisa fazer e depois chama o atualiza() enviando as visitas filtradas.

Duplicação de informações pode ser tanto algum problema ao voltar para uma Activity, por exemplo, como também, o fato de executar uma instrução de atualização sincrona e uma outra assincrona, assim como é a AsyncTask e uma interferir a outra na hora da atualização. É dificil responder com precisão sem simular/testar e realizar as analises.

[]s

Bom dia, Alex. Tudo ótimo e contigo?

Desculpe-me a demora, fiquei sem notebook por alguns dias. Troquei o HD para um SSD. Rapaz, ficou uma maravilha agora kkkkkk

Vamos lá... Custei para entender o que estava acontecendo de forma síncrona e assíncrona, mas ACHO que agora ficou mais claro.

Simplifiquei para a task já retornar a lista filtrada que eu quero e, assim, passar só ela para o atualiza().

    public void configuraAdapter(RecyclerView listaDeVisitas) {

        new Busca_TODAS_Visitas_Pela_SituacaoTask(situacaoDAO, visitaDAO, encontradas -> {
            Log.i("Teste", Integer.toString(encontradas.size()));

//Fiquei até na dúvida se eu tinha que colocar tudo aqui ou se aceitava só o atualiza, por exemplo, mas coloquei para testar

            adapter.atualiza(encontradas);
            listaDeVisitas.setAdapter(adapter);
            configuraItemTouchHelper(listaDeVisitas);
            adapter.setOnItemClickListener(new OnItemClickListener() {
                @Override
                public void OnItemClick(Visita visita, int posicao) {
                    new buscaVisitaPeloId(dao, visita, encontrada -> {
                        vaiParaEditaVisita(encontrada);
                    }).execute();
                }
            });
        });
    }

Só que não acontece "nada". O adapter não atualiza nem as informações aparecem no log para eu ver se passaram o tamanho correto para não dar NPE. O processo está tão demorado assim ou o raciocínio continua errado? Hahaha

A nova task ficou:

public class Busca_TODAS_Visitas_Pela_SituacaoTask extends AsyncTask<Void, Void, List<Visita>> {

    private final RoomSituacaoDAO situacaoDAO;
    private final RoomVisitaDAO visitaDAO;
    private final encontradasListener listener;

    public Busca_TODAS_Visitas_Pela_SituacaoTask(RoomSituacaoDAO situacaoDAO, RoomVisitaDAO visitaDAO, encontradasListener listener) {
        this.situacaoDAO = situacaoDAO;
        this.visitaDAO = visitaDAO;
        this.listener = listener;
    }

    @Override
    protected List<Visita> doInBackground(Void... voids) {
        return visitaDAO.todos();
    }

    @Override
    protected void onPostExecute(List<Visita> visitasEncontradas) {
        super.onPostExecute(visitasEncontradas);
        List<Visita> visitasFiltradas = new ArrayList<>();
        Log.i("Teste", Integer.toString(visitasEncontradas.size()));
        if (visitasEncontradas != null) {
            for (int i = 0; i < visitasEncontradas.size(); i++) {
                int id_Situacao = visitasEncontradas.get(i).getSituacao_id();
                String situacaoEncontrada = situacaoDAO.buscaPorId(id_Situacao);
                if (situacaoEncontrada.equals(SITUACAO_CONTATO_ESCOLA_PARA) || situacaoEncontrada.equals(SITUACAO_AMBIENTACAO_PARA))
                    visitasFiltradas.add(visitasEncontradas.get(i));
            }
        }
        listener.quandoencontradas(visitasFiltradas);
    }

    public interface encontradasListener {
        void quandoencontradas(List<Visita> visitasEncontradas);
    }
}

Tudo tranquilo! Com a mudança para SSD realmente vira um outro computador hehe

Se não está acontecendo nada, provavelmente a task não está sendo executada. Você precisa chamar o execute da sua task.

Você sabe que isso acontece com os melhores alunos né? hahaha

Tive que fazer alguns ajustes, mas funcionou. Agora entendi o conceito!!!!!!

Muitíssimo obrigado, Alex.

Quer mergulhar em tecnologia e aprendizagem?

Receba a newsletter que o nosso CEO escreve pessoalmente, com insights do mercado de trabalho, ciência e desenvolvimento de software