Android创建BitmapDescriptorexception

我正在编写一个应用程序,可以使用谷歌地图和标记。 我的任务是在谷歌地图上创建和显示一些标记。 标记中包含自定义图像和文本。 数据从服务器加载,我需要每次用户移动谷歌地图相机时显示新的数据量。 所以我使用android-maps-utils:0.4.3库来创建自定义Bitmap(使用IconGenerator),然后从中创建BitmapDescriptor。 以下是代码的一部分:

googleMap.clear() LayoutInflater layoutInflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); IconGenerator clusterIconGenerator = new IconGenerator(getActivity()); View clusterView = layoutInflater.inflate(R.layout.marker_cluster_view, null, false); clusterIconGenerator.setContentView(clusterView); clusterIconGenerator.setBackground(ContextCompat.getDrawable(getActivity(), R.drawable.mark_normal_grey)); List clusters = result.getResult(); // server data for (Cluster cluster : clusters) { Bitmap bitmap = clusterIconGenerator.makeIcon(String.valueOf(cluster.getOffersCount())); Marker marker = googleMap.addMarker(new MarkerOptions() .position(new LatLng(cluster.getLocation().getLatitude(), cluster.getLocation().getLongitude())) .icon(BitmapDescriptorFactory.fromBitmap(bitmap)) // crash here .anchor(0.5f, 0.5f)); markerClusterMap.put(marker, cluster); } 

一切都很好,除了应用程序崩溃有时(不经常)有2个不同的例外:

  java.lang.RuntimeException: Could not copy bitmap to parcel blob. at android.graphics.Bitmap.nativeWriteToParcel(Native Method) at android.graphics.Bitmap.writeToParcel(Bitmap.java:1541) at com.google.android.gms.maps.model.aca(:com.google.android.gms:237) at com.google.android.gms.maps.internal.ha(:com.google.android.gms:227) at com.google.android.gms.maps.internal.ja(:com.google.android.gms:183) at com.google.android.gms.maps.internal.CreatorImpl.a(:com.google.android.gms:32) at com.google.android.gms.maps.internal.ba(:com.google.android.gms:227) at com.google.android.gms.maps.model.abonTransact(:com.google.android.gms:106) at android.os.Binder.transact(Binder.java:387) at com.google.android.gms.maps.model.internal.zza$zza$zza.zzc(Unknown Source) at com.google.android.gms.maps.model.BitmapDescriptorFactory.fromBitmap(Unknown Source) at com.cheapsta.cheapsta.fragments.GoogleMapFragment.clustersLoadingFinished(GoogleMapFragment.java:187) 

而有时

 java.lang.RuntimeException: Could not allocate dup blob fd. at android.graphics.Bitmap.nativeCreateFromParcel(Native Method) at android.graphics.Bitmap.-wrap0(Bitmap.java) at android.graphics.Bitmap$1.createFromParcel(Bitmap.java:1516) at android.graphics.Bitmap$1.createFromParcel(Bitmap.java:1515) at maps.bx.a$a.onTransact(:com.google.android.gms.alldynamite:101) at android.os.Binder.transact(Binder.java:387) at com.google.android.gms.maps.model.aca(:com.google.android.gms:242) at com.google.android.gms.maps.internal.ha(:com.google.android.gms:227) at com.google.android.gms.maps.internal.ja(:com.google.android.gms:183) at com.google.android.gms.maps.internal.CreatorImpl.a(:com.google.android.gms:32) at com.google.android.gms.maps.internal.ba(:com.google.android.gms:227) at com.google.android.gms.maps.model.abonTransact(:com.google.android.gms:106) at android.os.Binder.transact(Binder.java:387) at com.google.android.gms.maps.model.internal.zza$zza$zza.zzc(Unknown Source) at com.google.android.gms.maps.model.BitmapDescriptorFactory.fromBitmap(Unknown Source) at com.cheapsta.cheapsta.fragments.GoogleMapFragment.clustersLoadingFinished(GoogleMapFragment.java:187) 

我该怎么办? 我想我正在使用我的内存来创建BitmapDescriptors。 如果用户移动相机太多,那么每3秒就有近20个BitmapDescriptos。 我应该以某种方式缓存它吗? 对你的答案和时间感兴趣!

那么这就是我得到的。 看起来BitmapFactory如果没有内存就无法创建Bitmap。 因此,如果GC没有工作,你没有足够的内存,你会得到这个例外。 在我的情况下,这通常是因为每次用户移动谷歌地图相机时我需要生成大约10-20个标记。

首先,不要像我一样愚蠢,不要只为IconGenerator使用android-maps-utils :)我编写了自己的类,从Bitmap生成BitmapDescriptor并将其缓存在LruCache中。 这是缓存Bitmaps 的好教程 。 您可以为BitmapDescriptor执行几乎相同的操作。 注意LruCache的大小。 您不能以字节为单位获取BitmapDescriptor大小,因此您需要考虑LruCache中这些对象的数量。 只需查看您的位图大小并进行一些计算。

如果您的图像中需要文字,请执行以下操作:

 Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), R.drawable.mark_active_grey).copy(Bitmap.Config.ARGB_8888, true); Canvas canvas = new Canvas(bitmap); canvas.drawText(offersCount, canvas.getWidth()/2, canvas.getHeight()/2 - ((clustersPaint.getFontMetrics().ascent + clustersPaint.getFontMetrics().descent) / 2) , clustersPaint); 

对不起英语不好,我希望这些信息对某些人有用。

我有同样的问题。 有了Kuva的回答,我创建了一个像这样的新课程:

 public class MapBmpContainter { private int mBmpSize; public BitmapDescriptor mBmpDescriptor; public MapBmpContainter(Bitmap bmp) { mBmpSize=bmp.getByteCount()/1014; mBmpDescriptor= BitmapDescriptorFactory.fromBitmap(bmp); } public int getSize() { return mBmpSize; } } 

我在LruCache中缓存新的类对象而不是Bitmap。 与Kuva相同我认为Bitmap和BitmapDescriptor几乎相同。 它奏效了

对我来说,问题与图标的大小有关。 我只是动态地改变位图的大小并且工作正常。

Bitmap image2 = Bitmap.createScaledBitmap(iconBitmap,120,120,false);

使用Picasso,Glide或Fresco Literary高效缓存位图。

  Picasso.with(getContext()) .load(R.drawable.marker) .resize(width, width) .into(new Target() { @Override public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) { markerOptionsHome = new MarkerOptions(); markerOptionsHome.title("Home location"); markerOptionsHome.snippet(""); markerOptionsHome.position(latlng); markerOptionsHome.icon(BitmapDescriptorFactory.fromBitmap(bitmap)); homeLocationMarker = map.addMarker(markerOptionsHome); } @Override public void onBitmapFailed(Drawable errorDrawable) { } @Override public void onPrepareLoad(Drawable placeHolderDrawable) { } });