Android创建BitmapDescriptor异常

Kuv*_*uva 5 java android google-maps google-maps-markers google-maps-android-api-2

我正在编写一个应用程序,可以使用谷歌地图和标记.我的任务是在谷歌地图上创建和显示一些标记.标记中包含自定义图像和文本.数据从服务器加载,我需要每次用户移动谷歌地图相机时显示新的数据量.所以我使用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<Cluster> 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);
        }
Run Code Online (Sandbox Code Playgroud)

一切都很好,除了应用程序崩溃有时(不经常)有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.a.c.a(:com.google.android.gms:237)
                                                                     at com.google.android.gms.maps.internal.h.a(:com.google.android.gms:227)
                                                                     at com.google.android.gms.maps.internal.j.a(: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.b.a(:com.google.android.gms:227)
                                                                     at com.google.android.gms.maps.model.a.b.onTransact(: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)
Run Code Online (Sandbox Code Playgroud)

而有时

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.a.c.a(:com.google.android.gms:242)
                                                                       at com.google.android.gms.maps.internal.h.a(:com.google.android.gms:227)
                                                                       at com.google.android.gms.maps.internal.j.a(: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.b.a(:com.google.android.gms:227)
                                                                       at com.google.android.gms.maps.model.a.b.onTransact(: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)
Run Code Online (Sandbox Code Playgroud)

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

Kuv*_*uva 11

那么这就是我得到的.看起来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);
Run Code Online (Sandbox Code Playgroud)

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

  • 我现在没有IconGenerator的例子.但其中的LruCache与Google教程中的缓存位图几乎相同(链接在我的anser中).是的sizeOf是一个问题.我刚刚计算了我的Bitmap的内存大小,并建议BitmapDescriptor的大小几乎相同.所以我计算出尺寸= 100 BitMapDescriptors的LruCach最大内存为1.6 MB.一切都很好.我根本没有任何记忆问题. (3认同)