Android:如何在使用Picasso下载图片后重新加载自定义标记?

4
我正在尝试将用户头像作为自定义标记动态加载。我基于Google Maps Utils演示代码编写,但不知何故它无法正常工作,只加载了一个图像,而其他所有图像都为空:

enter image description here

这是我的代码:

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());
        }

    }

有什么想法吗?

编辑:我意识到有时它确实会加载所有图像,我认为问题来自异步任务。所以我的问题现在是:如果我实现一个回调函数来知道Picasso何时完成加载图像,我该如何重新加载特定的标记?


是的。Picasso确实有回调方法。我有一个信息窗口回调的示例,请看这里。此外,在官方文档中,它有一个Target对象,其中包含用于视图的回调。您可以使用.into(Target target) - bjiang
标记的答案没有帮助。使用这个 http://stackoverflow.com/a/29015489/994926。这对我有用。 - Navdroid
3个回答

6
我们将从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) {
            }
        });

我也遇到了一些关于Picasso的问题。因此,我建议使用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));
                    }
                }
            });

现在它不显示任何图像,只有标准的图钉...也许我应该以某种方式使用这个?
Bitmap icon = mIconGenerator.makeIcon(); markerOptions.icon(BitmapDescriptorFactory.fromBitmap(icon)).title(user.getName());
- Kalianey
@KaliAney 是的,我也遇到了 Picasso 的问题。看看 Glide 吧,我更新了我的答案。 - Stas Parshin
它可以运行,谢谢!虽然如果我放大图片仍然存在一些显示问题,但如果我无法解决它,我会问另一个问题 :) - Kalianey

1
关于@Stas Parshin的回答,如果您将请求放在onBeforeClusterItemRendered()中可能会出现一些问题。我将其放在onClusterItemRendered()上,它运行得非常好。这是因为Glide正在使用异步进程,可能无法及时将其加载到ImageView中。希望这可以帮助到您。

1

你好,之前的答案是使用库来实现的,这里提供一种使用本地代码的另一种方法。

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;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接