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

Problema para carregar uma lista no maps - Help urgente!

Pessoal estou desenvolvendo um aplicativo para meu tcc, com base no curso de Android III, a parte que usa o maps e coloca uma aluno lá de acordo com o endereço dele. Só que a minha vai exibir os estabelecimentos cadastrados, estou usando o servidor do Firebase como back-end , e preciso baixar a lista dos meus estabelecimentos de lá, para isso eu consulto e até ai tudo bem. O problema é em exibir essa lista no maps, ele usa várias threads para carregar parece e ele não deixa terminar de baixar minha lista do Firebase, ai dá o problema. Eu tentei resolver com notify e wait ,e AsyncTask e sem sucesso.

Se alguém poder ajudar agradeço muito, está muito em cima para mim e já pesquisei em muitos lugares e nada.

Segue meu código com notify e wait:

public class MapaFragment extends SupportMapFragment implements OnMapReadyCallback {

    private final DatabaseReference database;

    public static GoogleMap mapa;

    private List<Bar> bares;

    public MapaFragment(DatabaseReference database){

        this.database = database;
    }

    @Override
    public void onCreate(Bundle bundle) {
        super.onCreate(bundle);

        getMapAsync(this);
    }


    @Override
    public void onMapReady(GoogleMap googleMap) {

        this.mapa = googleMap;

        try {

            pegaBares();

            bares.wait();

            for(Bar bar : bares){
                Toast.makeText(getContext(), "dentro do for", Toast.LENGTH_LONG).show();
                Toast.makeText(getContext(), bar.getNome() + " - " + bar.getEndereco(), Toast.LENGTH_LONG).show();
                LatLng coordenada = pegaCoordenadaDoEndereco(bar.getEndereco());
                if(coordenada != null) {
                    MarkerOptions marcador = new MarkerOptions();
                    marcador.position(coordenada);
                    marcador.title(bar.getNome());
                    marcador.snippet(String.valueOf(bar.getTelefone()));
                    marcador.icon(BitmapDescriptorFactory.fromResource(R.drawable.copocheio));
                    MapaFragment.mapa.addMarker(marcador);

                }
            }

        } catch (InterruptedException e) {
            e.printStackTrace();
        }


        new Localizador(getContext(), MapaFragment.this);
    }



    private LatLng pegaCoordenadaDoEndereco(String endereco) {

        try{
            Geocoder geocoder = new Geocoder(getContext());
            List<Address> resultados = geocoder.getFromLocationName(endereco, 1);

            if(!resultados.isEmpty()){
                LatLng posicao = new LatLng(resultados.get(0).getLatitude(),
                        resultados.get(0).getLongitude());
                return posicao;
            }

        }catch(IOException e){
            e.printStackTrace();
        }
        return null;
    }

    public void centralizaEm(LatLng coordenada){
        if(mapa != null){
            CameraUpdate update = CameraUpdateFactory.newLatLngZoom(coordenada, 17);
            mapa.moveCamera(update);

            MarkerOptions marcador = new MarkerOptions();
            marcador.position(coordenada);
            marcador.icon(BitmapDescriptorFactory.fromResource(R.drawable.copovazio));
            mapa.addMarker(marcador);
        }
    }

    private void pegaBares() {

        bares = new ArrayList<>();

        database.addValueEventListener(new ValueEventListener() {
            @Override
            public void onDataChange(DataSnapshot dataSnapshot) {

                for (DataSnapshot snapshot : dataSnapshot.getChildren()){
                    Map<String, Object> map = (HashMap<String, Object>) snapshot.getValue();

                    String nome = String.valueOf(map.get("nome"));
                    String endereco = String.valueOf(map.get("endereco"));
                    String telefone = String.valueOf(map.get("telefone"));
                    String site = String.valueOf(map.get("site"));
                    String email = String.valueOf(map.get("email"));

                    if (endereco != null) {
                        Bar bar = new Bar(nome, endereco, telefone, site, email);

                        bares.add(bar);


                    }
                }
            }

            @Override
            public void onCancelled(DatabaseError databaseError) {

            }
        });

        bares.notify();
    }

}

dando esse erro:

09-30 16:43:23.632 17412-17412/br.com.tcc.searchdrink E/UncaughtException: java.lang.IllegalMonitorStateException: object not locked by thread before notify()
                                                                               at java.lang.Object.notify(Native Method)
                                                                               at br.com.alura.searchdrink.fragment.MapaFragment.pegaBares(MapaFragment.java:198)
                                                                               at br.com.alura.searchdrink.fragment.MapaFragment.onMapReady(MapaFragment.java:91)
                                                                               at com.google.android.gms.maps.SupportMapFragment$zza$1.zza(Unknown Source)
                                                                               at com.google.android.gms.maps.internal.zzt$zza.onTransact(Unknown Source)
                                                                               at android.os.Binder.transact(Binder.java:385)
                                                                               at wl.a(:com.google.android.gms.DynamiteModulesB:82)
                                                                               at maps.ad.t$5.run(Unknown Source)
                                                                               at android.os.Handler.handleCallback(Handler.java:815)
                                                                               at android.os.Handler.dispatchMessage(Handler.java:104)
                                                                               at android.os.Looper.loop(Looper.java:194)
                                                                               at android.app.ActivityThread.main(ActivityThread.java:5717)
                                                                               at java.lang.reflect.Method.invoke(Native Method)
                                                                               at java.lang.reflect.Method.invoke(Method.java:372)
                                                                               at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:959)
                                                                               at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:754)

De outra forma, com AsyncTask, esse não deu erro nenhum porém não sei porque ele não está carregando os estabelecimentos no mapa, parece que ele começa o doInBackgrournd e pula sem terminar o database.addValueEventListener indo pro onPostExecute de uma vez, fiz um log lá com o tamanho da lista e dá 0, estranho , não sei se estou usando incorretamente os atributos, e estou instanciando e dando o execute com ela dentro do MapaFragment mesmo, no método onMapReady:

public class TarefaDownloadLocalizacaoBares extends AsyncTask<String, Void, List<Bar>> {

    private final Context context;
    private final DatabaseReference database;

    private ProgressDialog progresso;

    public TarefaDownloadLocalizacaoBares(Context context, DatabaseReference database){
        this.context = context;
        this.database = database;
    }

    @Override
    protected void onPreExecute() {
        Log.i("AsyncTask", "Exibindo ProgressDialog na tela Thread: " + Thread.currentThread().getName());
        progresso = ProgressDialog.show(context, "Por favor Aguarde ...",
                "Baixando Bares...");
    }

    @Override
    protected List<Bar> doInBackground(String... strings) {

        final List<Bar> estabelecimentos = new ArrayList<>();

            database.addValueEventListener(new ValueEventListener() {
                @Override
                public void onDataChange(DataSnapshot dataSnapshot) {

                    for (DataSnapshot snapshot : dataSnapshot.getChildren()) {

                        Map<String, Object> map = (HashMap<String, Object>) snapshot.getValue();

                        String nome = String.valueOf(map.get("nome"));
                        String endereco = String.valueOf(map.get("endereco"));
                        String telefone = String.valueOf(map.get("telefone"));
                        String site = String.valueOf(map.get("site"));
                        String email = String.valueOf(map.get("email"));

                        if (endereco != null) {
                            Bar bar = new Bar(nome, endereco, telefone, site, email);

                            estabelecimentos.add(bar);


                        }
                    }
                }

                @Override
                public void onCancelled(DatabaseError databaseError) {

                }
            });

        return estabelecimentos;
    }

    @Override
    protected void onPostExecute(List<Bar> bares) {

        progresso.dismiss();

        //adiciona local do bar
        for(Bar bar : bares){
            Toast.makeText(context, "dentro do for", Toast.LENGTH_LONG).show();
            Toast.makeText(context, bar.getNome() + " - " + bar.getEndereco(), Toast.LENGTH_LONG).show();
            LatLng coordenada = pegaCoordenadaDoEndereco(bar.getEndereco());
            if(coordenada != null) {
                MarkerOptions marcador = new MarkerOptions();
                marcador.position(coordenada);
                marcador.title(bar.getNome());
                marcador.snippet(String.valueOf(bar.getTelefone()));
                marcador.icon(BitmapDescriptorFactory.fromResource(R.drawable.copocheio));
                MapaFragment.mapa.addMarker(marcador);

            }
        }

    }

    private LatLng pegaCoordenadaDoEndereco(String endereco) {

        try{
            Geocoder geocoder = new Geocoder(context);
            List<Address> resultados = geocoder.getFromLocationName(endereco, 1);

            if(!resultados.isEmpty()){
                LatLng posicao = new LatLng(resultados.get(0).getLatitude(),
                        resultados.get(0).getLongitude());
                return posicao;
            }

        }catch(IOException e){
            e.printStackTrace();
        }
        return null;
    }
}

E no MapaFragment no método onMapReady:

@Override
public void onMapReady(GoogleMap googleMap) {

    this.mapa = googleMap;

    TarefaDownloadLocalizacaoBares downloadLocalizacaoBares = new TarefaDownloadLocalizacaoBares(getContext(), database);
    downloadLocalizacaoBares.execute();

    new Localizador(getContext(), MapaFragment.this);
}
2 respostas
solução!

Oi Lucas

O erro que está dando é que voce so pode dar .wait em um objeto o qual a sua thread tem lock, isso é, que voce tenha feito syncrhonized nele. Mas imagino que, mesmo arrumando isso, sua lista nao vai aparecer.

O listener adicionado em database.addValueEventListener está sendo chamado? Ou nunca?

Oi Paulo, obrigado pela atenção, sua dica me ajudou muito, estava usando incorretamente o semáforo, olha como ficou o código para funcionar, e eu acabei usando o método do AsynTask:

public class TarefaDownloadLocalizacaoBares extends AsyncTask<DatabaseReference, Void, List<Bar>> {

    private final Context context;

    private final List<Bar> estabelecimentos;

    private ProgressDialog progresso;

    public TarefaDownloadLocalizacaoBares(Context context, List<Bar> bares){
        this.estabelecimentos = bares;
        this.context = context;
    }

    @Override
    protected void onPreExecute() {
        Log.i("AsyncTask", "Exibindo ProgressDialog na tela Thread: " + Thread.currentThread().getName());
        progresso = ProgressDialog.show(context, "Por favor Aguarde ...",
                "Baixando Bares...");
    }

    @Override
    protected List<Bar> doInBackground(DatabaseReference... dbs) {
        Log.i("AsyncTask", "Exibindo ProgressDialog na tela Thread 1: " + Thread.currentThread().getName());

            dbs[0].addValueEventListener(new ValueEventListener() {
                @Override
                public void onDataChange(DataSnapshot dataSnapshot) {
                    Log.i("AsyncTask", "Exibindo ProgressDialog na tela Thread 2: " + Thread.currentThread().getName());

                    synchronized (estabelecimentos) {

                        for (DataSnapshot snapshot : dataSnapshot.getChildren()) {
                            Log.i("AsyncTask", "Exibindo ProgressDialog na tela Thread 3: " + Thread.currentThread().getName());

                            Map<String, Object> map = (HashMap<String, Object>) snapshot.getValue();

                            String nome = String.valueOf(map.get("nome"));
                            String endereco = String.valueOf(map.get("endereco"));
                            String telefone = String.valueOf(map.get("telefone"));
                            String site = String.valueOf(map.get("site"));
                            String email = String.valueOf(map.get("email"));

                            if (endereco != null) {
                                Bar bar = new Bar(nome, endereco, telefone, site, email);
                                estabelecimentos.add(bar);
                            }
                        }

                    estabelecimentos.notifyAll();

                    }
                }

                @Override
                public void onCancelled(DatabaseError databaseError) {

                }
            });

        synchronized (estabelecimentos){
            try {
                estabelecimentos.wait();
            } catch (InterruptedException e) {e.printStackTrace();}
        }

        return estabelecimentos;
    }

    @Override
    protected void onPostExecute(List<Bar> bares) {

        progresso.dismiss();

        Toast.makeText(context, "tamanho da lista: " + bares.size(), Toast.LENGTH_LONG).show();

        //adiciona local do bar
        for(Bar bar : bares){
//            Toast.makeText(context, "dentro do for", Toast.LENGTH_LONG).show();
//            Toast.makeText(context, bar.getNome() + " - " + bar.getEndereco(), Toast.LENGTH_LONG).show();
            LatLng coordenada = pegaCoordenadaDoEndereco(bar.getEndereco());
            if(coordenada != null) {
                MarkerOptions marcador = new MarkerOptions();
                marcador.position(coordenada);
                marcador.title(bar.getNome());
                marcador.snippet(String.valueOf(bar.getTelefone()));
                marcador.icon(BitmapDescriptorFactory.fromResource(R.drawable.copocheio));
                MapaFragment.mapa.addMarker(marcador);

            }
        }

    }

    private LatLng pegaCoordenadaDoEndereco(String endereco) {

        try{
            Geocoder geocoder = new Geocoder(context);
            List<Address> resultados = geocoder.getFromLocationName(endereco, 1);

            if(!resultados.isEmpty()){
                LatLng posicao = new LatLng(resultados.get(0).getLatitude(),
                        resultados.get(0).getLongitude());
                return posicao;
            }

        }catch(IOException e){
            e.printStackTrace();
        }
        return null;
    }
}