Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android google maps async task add markers

I have a map. I have a database of points. I want to display points from database in AsyncTask, so user can move around the map, when the points are being loaded. There's not much points (like 353 or etc), but I redraw them all when user gets closer (zoom) to the map with bigger markers. When this redraw occurs, app freezes like for a fraction of a second, but it's noticeable, so I thought AsyncTask would be the answer.

However it's not working. And it's weird. I found a few questions here, but the problem there was mostly not calling the "publishProgress()" method, which is not my case.

In the method "doInBackground()" I open the database, do the query and save it to a Cursor (which is attribute of my ShowPoints class, which extends AsyncTask, so it shoud be accesable by all methods of this class //at least I think that). Than I go through the cursor and each time call "publishProgress()" which shoud call "onProgressUpdate()" and here I create the marker using my cursor from "doInBackgroud()".

It's strange that if I do debug, and go through the code by step, it all works as it shoud. But when I run the app, no markers are added or only a few of them.

private class ShowPoints extends AsyncTask<String, Integer, String> {

      private String resp="Body načteny";
      private Cursor c_body;
      private LatLng marker_pozice;

      @Override
      protected String doInBackground(String... params) {
          int i=0;
       try {
           DatabaseHelper db = new DatabaseHelper(MainActivity.this);
            try {

                db.openDataBase();

            }catch(SQLException sqle){

                throw sqle;

            }
            c_body = db.query(DatabaseHelper.TABLE_POINTS, allColumns, null, null, null,null, null);
            if(c_body.moveToFirst())
            {
                if(params[0]=="small"){
                    do {
                            i++;
                        int ikona = R.drawable.gray_dot;
                        int trasa = c_body.getInt(6);
                        switch(trasa){
                        case 1: ikona = R.drawable.color_00a750_dot;
                        break;
                        case 2: ikona = R.drawable.color_ec1c24_dot;
                        break;
                        case 3: ikona = R.drawable.color_ffca05_dot;
                        break;
                        case 4: ikona = R.drawable.color_6dcef5_dot;
                        break;
                        case 5: ikona = R.drawable.color_f497b0_dot;
                        break;
                        case 6: ikona = R.drawable.color_0088cf_dot;
                        break;
                        case 7: ikona = R.drawable.color_98d3bf_dot;
                        break;
                        case 8: ikona = R.drawable.color_c3792f_dot;
                        break;
                        case 9: ikona = R.drawable.color_c5168c_dot;
                        break;
                        }
                    publishProgress(ikona);
                    Log.i("Thread",String.valueOf(i));


                         } while (c_body.moveToNext());
                }else{
                         do {
                        i++;
                        int ikona = R.drawable.bigg_dot;
                        int trasa = c_body.getInt(6);
                        switch(trasa){
                        case 1: ikona = R.drawable.biggr_00a750_dot;
                        break;
                        case 2: ikona = R.drawable.biggr_ec1c24_dot;
                        break;
                        case 3: ikona = R.drawable.biggr_ffca05_dot;
                        break;
                        case 4: ikona = R.drawable.biggr_6dcef5_dot;
                        break;
                        case 5: ikona = R.drawable.biggr_f497b0_dot;
                        break;
                        case 6: ikona = R.drawable.biggr_0088cf_dot;
                        break;
                        case 7: ikona = R.drawable.biggr_98d3bf_dot;
                        break;
                        case 8: ikona = R.drawable.biggr_c3792f_dot;
                        break;
                        case 9: ikona = R.drawable.biggr_c5168c_dot;
                        break;
                        }
                        Log.i("Thread",String.valueOf(i));
                    publishProgress(ikona);

                         } while (c_body.moveToNext());
                }
            }
            db.close();
       } catch (Exception e) {
        e.printStackTrace();
        resp = e.getMessage();
       }
       return resp;
      }

@Override
      protected void onProgressUpdate(Integer... ikona) {
            marker_pozice = new LatLng(c_body.getDouble(3), c_body.getDouble(4));                 
            mMap.addMarker(new MarkerOptions()
              .position(marker_pozice)
              .title(c_body.getString(2))
              .snippet(c_body.getString(7)+"\n"+c_body.getString(1))
              .icon(BitmapDescriptorFactory.fromResource(ikona[0])));
            }
       // progress. For example updating ProgessDialog
      }

I call this in the onCreate method:

ShowPoints pointShower = new ShowPoints();
pointShower.execute("small");

Also the logging I'm doing in "doInBackgroud()" works, but markers are not added to the map (or not all of them ... sometimes there are drawn 3, sometimes 19 etc).

mMap is accesable, because this class is inside another class, where the map is an attribute and is instantiated before this Async is called. Also as I'm saying, in debuger step by step I can draw all the points.

Also in "onPostExecute()" I have a toast, which is displayed when I launch the app, so there's no doubt it finishes the async (logging works, final method is called).

like image 745
ezpzlmnsqz1337 Avatar asked Nov 02 '22 03:11

ezpzlmnsqz1337


2 Answers

While your intentions here are good, I just dont see much gain from it because you are still calling back to the UI thread for every single element and I bet you wont see much of a difference in performance. Having said that I am willing to bet your problem is that you are holding onto the cursor and using that in the onProgressUpdate while your doInBackground continues on movine the cursor to the next row. Which would explain why when you debug it works correctly because you are stepping along.

What I would recommend for performance increase would be to in your doInBackground create a list of some object that holds all the information about the map object (icon,position, etc..). Only add the markers to the map where they are in the visible bounding box of the map so you are not plotting markers that are not even visible. then in your onPostExecute use that list and plot everything there.

While I dont know for sure if this is the cause of the problem but it could very well likely be the problem

like image 139
tyczj Avatar answered Nov 08 '22 11:11

tyczj


I do this by creating a list of MarkerOptions in the asynctask then in the onPostExecute I add these to the map in a loop. Actually I have two tasks that run syncronously. Task1 sets up the list of markeroptions and when it finishes task2 starts and gets / downloads any icon associated with the marker. I do the downloads at the end because chances are you'll reuse markers and you can use a hash to get a previously downloaded marker. You'd probably just be using the 2nd async task which gets the marker icons so as small favor I've included the class I use to get the bitmaps for markers.

Here's a custom class to handle the crp.

package com.gosylvester.bestrides.beans;

import com.google.android.gms.maps.model.MarkerOptions;

public class KmlMarkerOptions  {

    public MarkerOptions markeroptions;
    public String href;
    public int hrefhash =-1;
}

here's the 2nd async task that loads the bitmaps for the markers.

private class LoadMarkerBitmapDescriptor extends
            AsyncTask<List<KmlMarkerOptions>, Void, Boolean> {

        @Override
        protected Boolean doInBackground(List<KmlMarkerOptions>... params) {
            Boolean ret = true;
            List<KmlMarkerOptions> kmlmarkeroptions = params[0];
            int markerSize = kmlmarkeroptions.size();
            for (int currentMarkerPosition = 0; currentMarkerPosition < markerSize; currentMarkerPosition++) {
                KmlMarkerOptions currentMarkerOptions = kmlmarkeroptions
                        .get(currentMarkerPosition);
                int hrefhash = currentMarkerOptions.hrefhash;
                if (hrefhash != -1) {
                    // not the poistion zero marker
                    if (currentMarkerPosition != 0) {
                        // search for an existing bitmap descriptor
                        for (int previousMarkerPosition = 0; previousMarkerPosition < currentMarkerPosition; previousMarkerPosition++) {
                            KmlMarkerOptions previousMarkerOptions = kmlmarkeroptions
                                    .get(previousMarkerPosition);
                            if (previousMarkerOptions.hrefhash == hrefhash) {
                                currentMarkerOptions.markeroptions
                                        .icon(previousMarkerOptions.markeroptions
                                                .getIcon());
                                break;
                            }
                        }
                    }
                    if (currentMarkerOptions.markeroptions.getIcon() == null) {
                        try {
                            InputStream is = (InputStream) new URL(
                                    currentMarkerOptions.href).getContent();
                            Bitmap bm = (Bitmap) BitmapFactory.decodeStream(is);
                            currentMarkerOptions.markeroptions
                                    .icon((BitmapDescriptor) BitmapDescriptorFactory
                                            .fromBitmap(bm));
                        } catch (Exception e1) {
                            e1.printStackTrace();
                            ret = false;
                        }
                    }
                }
            }

            return ret;
        }


protected void onPostExecute(Boolean result) {
    addIcontoMap();         
}


protected void addIcontoMap() {
        for (KmlMarkerOptions kmlmo : mKmlmo) {
            mMap.addMarker(kmlmo.markeroptions);
        }
        }
like image 34
danny117 Avatar answered Nov 08 '22 11:11

danny117