Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Adding markers from url with Picasso

I'm adding markers to my map from a url using the Picasso library

As a marker isn't an ImageView I tried to use a Target instead

for(int x =0; x < mapIcon_url.length; x++){

    Picasso.with(getActivity()).load(mapIcon_url[x]).resize(marker_size, marker_size+15).into(new Target() {

        @Override
        public void onSuccess(Bitmap b) {
            bitmapMarker = BitmapDescriptorFactory.fromBitmap(b);


            //create marker option
            if(b != null)
                markerOptions = new MarkerOptions().position(marker_position).icon(bitmapMarker));
            else
                markerOptions = new MarkerOptions().position(marker_position).icon(BitmapDescriptorFactory.fromResource(R.drawable.placeholder_pin)).snippet(String.valueOf(x));

            marker = map.addMarker(markerOptions);                              
        }

        @Override
        public void onError() {

            //create marker option                                  
            markerOptions = new MarkerOptions().position(marker_position).icon(BitmapDescriptorFactory.fromResource(R.drawable.placeholder_pin)).snippet(String.valueOf(x));
            marker = map.addMarker(markerOptions);

        }
    }); 
}   

I'm doing this in a loop to add about 20 markers but I find that on first run of the code only 5 or 7 markers are added so I've switched to using the lib and an AsyncTask like this.

for(int x =0; x < mapIcon_url.length; x++){

    new AddMarker().execute(mapIcon_url[x]);
}


public class AddMarker extends AsyncTask<String, Integer, BitmapDescriptor> {

    BitmapDescriptor bitmapMarker1;
    VenueDetails myVenue;

    @Override
    protected BitmapDescriptor doInBackground(String... url) {  
        myUrl = url[0];
        try {
            bitmapMarker1 = BitmapDescriptorFactory.fromBitmap(Picasso.with(getActivity()).load(myUrl).resize(marker_size, marker_size+15).get());
        } catch (IOException e) {
            e.printStackTrace();
        }

        return bitmapMarker1;
    }

    protected void onPostExecute(BitmapDescriptor icon) {

        try {

            map.addMarker(new MarkerOptions().position(marker_position).icon(icon)));

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

However I'm a bit worried this method could give me some issues when I have alot of markers say about 100. My question would be is this the best way to do this and if not what other options can I try.

like image 352
Hugo Boss Avatar asked Aug 31 '13 13:08

Hugo Boss


2 Answers

You have to keep a reference for each Target, otherwise the system automatically releases them when the garbage collector is invoked.

So, the better solution is add each Target to a HashSet and then in onBitmapLoaded() and onBitmapFailed methods from Target, remove the Target itself from the set.

Thank you for the suggestion, now my code work perfectly. Below the pieces of code that implement your suggestion.

[...]//Global var
  private Set<PoiTarget> poiTargets = new HashSet<PoiTarget>();
[...]    
 private void somewhere(){
    PoiTarget pt;
    for(Item item: data) {
        m = map.addMarker(new MarkerOptions()
               .position(new LatLng(item.latitude, item.longitude))
               .title(item.title));
        pt = new PoiTarget(m);
        poiTargets.add(pt);
        Picasso.with(context)
           .load(mapImageURLString)
           .into(pt);
    }
}
[...]
//--------------------------------------------------------
// Inner class
//--------------------------------------------------------
    class PoiTarget implements Target{
        private Marker m;

        public PoiTarget(Marker m) { this.m = m; }

        @Override public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
            m.setIcon(BitmapDescriptorFactory.fromBitmap(bitmap));
            poiTargets.remove(this);
            Tools.msg(" @+ Set bitmap for "+m.getTitle()+" PT size: #"+poiTargets.size());
        }

        @Override public void onBitmapFailed(Drawable errorDrawable) {
            Tools.msg(" @+ [ERROR] Don't set bitmap for "+m.getTitle());
            poiTargets.remove(this);
        }

        @Override public void onPrepareLoad(Drawable placeHolderDrawable) {

        }
    }
like image 116
Francesco Florio Avatar answered Oct 15 '22 18:10

Francesco Florio


You have to keep a reference for each Target, otherwise the system automatically releases them when the garbage collector is invoked.

So, the better solution is add each Target to a HashSet and then in onBitmapLoaded() and onBitmapFailed methods from Target, remove the Target itself from the set.

like image 29
icastell Avatar answered Oct 15 '22 17:10

icastell