Android: как перезагрузить пользовательские маркеры после загрузки изображения через Picasso?

Я пытаюсь загрузить динамические аватары пользователей в качестве настраиваемых маркеров. Я основал свой код на демо-версии google maps utils, но как-то он не работает, он загружает только одно изображение, а все остальные пустые:

Введите описание изображения здесь

Вот мой код:

public class MapsActivity extends FragmentActivity implements ClusterManager.OnClusterItemClickListener<ModelUser>, ClusterManager.OnClusterItemInfoWindowClickListener<ModelUser> { private ClusterManager<ModelUser> mClusterManager; private GoogleMap mMap; // Might be null if Google Play services APK is not available. private QueryAPI query = new QueryAPI(); private List<ModelUser> users = new ArrayList<ModelUser>(); ImageLoader imageLoader = AppController.getInstance().getImageLoader(); //UI NetworkImageView avatarImageView; TextView name; TextView infos; TextView distance; RelativeLayout detailView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_maps); setUpMapIfNeeded(); detailView = (RelativeLayout) findViewById(R.id.detailView); avatarImageView = (NetworkImageView) findViewById(R.id.imageView); name = (TextView) findViewById(R.id.name); infos = (TextView) findViewById(R.id.info); distance = (TextView) findViewById(R.id.distance); query.nearUsers(new QueryAPI.ApiResponse<List<ModelUser>>() { @Override public void onCompletion(List<ModelUser> result) { users = result; setUpClusterer(); } }); } @Override protected void onResume() { super.onResume(); setUpMapIfNeeded(); } private void setUpMap() { mMap.setMyLocationEnabled(true); } private void setUpClusterer() { // Position the map. getMap().moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(46.155115, 2.473060), 5)); // Initialize the manager with the context and the map. // (Activity extends context, so we can pass 'this' in the constructor.) mClusterManager = new ClusterManager<ModelUser>(this, getMap()); // Point the map's listeners at the listeners implemented by the cluster // manager. getMap().setOnCameraChangeListener(mClusterManager); getMap().setOnMarkerClickListener(mClusterManager); mClusterManager.setRenderer(new PersonRenderer()); mClusterManager.setOnClusterItemClickListener(this); mClusterManager.setOnClusterItemInfoWindowClickListener(this); // Add cluster items (markers) to the cluster manager. addItems(); } private void addItems() { for (int i = 0; i < users.size(); i++) { ModelUser user = users.get(i); mClusterManager.addItem(user); } } protected GoogleMap getMap() { setUpMapIfNeeded(); return mMap; } @Override public boolean onClusterItemClick(ModelUser item) { Log.d("User clicked:", item.getName()); avatarImageView.setImageUrl(item.getAvatar_url(), imageLoader); name.setText(item.getName()); infos.setText(item.getAge()); double d = Double.parseDouble(item.getDistance()); distance.setText( String.format("%.1f", d) + "Km"); detailView.setVisibility(View.VISIBLE); return false; } @Override public void onClusterItemInfoWindowClick(ModelUser item) { Log.d("User Window clicked:", item.getName()); } /** * Draws profile photos inside markers (using IconGenerator). * When there are multiple people in the cluster, draw multiple photos (using MultiDrawable). */ private class PersonRenderer extends DefaultClusterRenderer<ModelUser> { private final IconGenerator mIconGenerator = new IconGenerator(getApplicationContext()); private final UICircularImage mImageView; //private final int mDimension; public PersonRenderer() { super(getApplicationContext(), getMap(), mClusterManager); View profile = getLayoutInflater().inflate(R.layout.map_marker_item, null); mIconGenerator.setContentView(profile); mImageView = (UICircularImage) profile.findViewById(R.id.avatarImageView); } @Override protected void onBeforeClusterItemRendered(ModelUser user, MarkerOptions markerOptions) { // Draw a single person. // Set the info window to show their name. // mImageView.setImageUrl(user.getAvatar_url(), imageLoader); Picasso.with(getApplicationContext()) .load(user.getAvatar_url()) .noFade() .into(mImageView, new com.squareup.picasso.Callback() { @Override public void onSuccess() { //reload the marker HERE } @Override public void onError() { } }); Bitmap icon = mIconGenerator.makeIcon(); markerOptions.icon(BitmapDescriptorFactory.fromBitmap(icon)).title(user.getName()); } } 

Любая идея почему?

EDIT: Я понял, что иногда он загружает все изображения, я думаю, проблема возникает из задачи async. Итак, теперь мой вопрос: если я реализую обратный вызов, чтобы узнать, когда Picasso закончил загрузку изображения, как я могу перезагрузить этот конкретный маркер?

Мы загрузим растровое изображение из Picasso, а затем передадим его маркеру, представляющему текущего пользователя

 Picasso.with(getApplicationContext()) .load(user.getAvatar_url()) .into(new com.squareup.picasso.Target() { @Override public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) { // let's find marker for this user Marker markerToChange = null; for (Marker marker : mClusterManager.getMarkerCollection().getMarkers()) { if (marker.getPosition().equals(user.getPosition())) { markerToChange = marker; break; } } // if found - change icon if (markerToChange != null) { markerToChange.setIcon(BitmapDescriptorFactory.fromBitmap(bitmap)); } } @Override public void onBitmapFailed(Drawable errorDrawable) { } @Override public void onPrepareLoad(Drawable placeHolderDrawable) { } }); 

У меня тоже есть проблемы с Пикассо. Поэтому я рекомендую использовать Glide

 compile 'com.github.bumptech.glide:glide:3.5.2' Glide.with(getApplicationContext()). load(user.getAvatar_url()) .asBitmap() .fitCenter() .into(new SimpleTarget<Bitmap>() { @Override public void onResourceReady(Bitmap bitmap, GlideAnimation<? super Bitmap> glideAnimation) { // let's find marker for this user Marker markerToChange = null; for (Marker marker : mClusterManager.getMarkerCollection().getMarkers()) { if (marker.getPosition().equals(user.getPosition())) { markerToChange = marker; break; } } // if found - change icon if (markerToChange != null) { markerToChange.setIcon(BitmapDescriptorFactory.fromBitmap(bitmap)); } } }); 

Hello man предыдущий ответ работает с libs, и вот еще один ответ с собственным кодом

 private class DownloadImage extends AsyncTask<String, Void, Bitmap> { ImageView image; LatLng latLng; public DownloadImage (double lat, double lng) { this.latLng = new LatLng(lat, lng); } protected Bitmap doInBackground(String... urls) { String url = urls[0]; Bitmap bmpImg = null; try { InputStream in = new java.net.URL(url).openStream(); bmpImg = BitmapFactory.decodeStream(in); } catch (Exception e) { Log.e("image", e.toString()); } return bmpImg; } protected void onPostExecute(Bitmap bmpImg) { View viewLocationMarker = ((LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.marker_custom_view, null); ImageView imageView = (ImageView) viewLocationMarker.findViewById(R.id.imgPic); try { imageView.setImageBitmap(bmpImg); } catch (Exception e) { imageView.setImageResource(R.drawable.place_holder); } Marker locationMarker = mMap.addMarker(new MarkerOptions() .position(latLng).title("Sattar").anchor(0.33f, 1) .icon(BitmapDescriptorFactory.fromBitmap(createDrawableFromView(MapsActivity.this, viewLocationMarker)))); } } public static Bitmap createDrawableFromView(Context context, View view) { DisplayMetrics displayMetrics = new DisplayMetrics(); ((Activity) context).getWindowManager().getDefaultDisplay().getMetrics(displayMetrics); view.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)); view.measure(displayMetrics.widthPixels, displayMetrics.heightPixels); view.layout(0, 0, displayMetrics.widthPixels, displayMetrics.heightPixels); view.buildDrawingCache(); Bitmap bitmap = Bitmap.createBitmap(view.getMeasuredWidth(), view.getMeasuredHeight(), Bitmap.Config.ARGB_8888); Canvas canvas = new Canvas(bitmap); view.draw(canvas); return bitmap; } 

Что касается ответа @Stas Parshin, могут возникнуть проблемы с Glide, если вы поместите запрос в onBeforeClusterItemRendered.

Я разместил его onClusterItemRendered, и он работал красиво. Это связано с тем, что Glide использует асинхронный процесс и может не загружать его в ImageView вовремя.

Надеюсь, поможет.