3

Googleマップとマーカーで動作するアプリケーションを作成しています。私の仕事は、Googleマップ上にある量のマーカーを作成して表示することです。マーカーにはカスタム画像とテキストがあります。データはサーバーからロードされており、ユーザーがGoogleマップカメラを移動するたびに新しいデータ量を表示する必要があります。だから私はandroid-maps-utilsを使用しています:(IconGeneratorを使って)カスタムBitmapを作成し、それからBitmapDescriptorを作成するための0.4.3ライブラリ。ここでは、コードの一部です:何ができるBitmapDescriptorの例外を作成するAndroid

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) 

、時には

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) 

:アプリケーションが2つの異なる例外を除いて、時々クラッシュ(たまに)である以外

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

すべてはokです私はこれでやる? BitmapDescriptorsを作成するために私のメモリを多用していると思います。ユーザーがカメラをあまりに多く動かすと、3秒ごとにほぼ20のBitmapDescriptosになります。私は何とかそれをキャッシュする必要がありますか?あなたの答えと時間のために多くのThx!

答えて

4

ここに私が得たものがあります。 bitmapFactoryのように、ビットマップが十分なメモリを持っていない場合は作成できません。 GCが仕事をしておらず、十分な記憶がない場合、この例外が発生します。私の場合は、ユーザーがGoogleマップカメラを動かすたびに約10〜20個のマーカーを生成する必要があるため、かなり頻繁に使用されていました。

まず、私のように愚かではなく、IconGeneratorのためだけにandroid-maps-utilsを使用しないでください:) BitmapからBitmapDescriptorを生成してLruCacheにキャッシュする独自のクラスを作成しました。ビットマップをキャッシュするためのHere's good tutorial。 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); 
の悪い英語のため申し訳ありません

と私は、この情報はいくつかのいずれかに役立つことを願っています。

+0

あなたは 'BitmapDescriptor'のための' 'LruCache'とIconGenerator'の例を持っていて、ビットマップのサイズに関しては、' sizeOf'を解決し、特にどのようにか? – Dellkan

+2

私は現在、私のIconGeneratorの例は持っていません。しかし、その中のLruCacheはビットマップのキャッシュに関する私のアンサーのリンクとほぼ同じです。そしてsizeOfは問題です。私はちょうど私のビットマップのメモリサイズを計算し、BitmapDescriptorがほぼ同じサイズになることを提案しました。だから私はサイズ= 100 BitMapDescriptorsのLruCachは最大1.6メガバイトのメモリになると計算した。そしてすべてが大丈夫だった。私は全く記憶上の問題はありませんでした。 – Kuva

1

同じ問題がありました。クヴァの答えでは、私はこのような新しいクラスを作成します。

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に新しいクラスオブジェクトをキャッシュします。 Kuvaと同じBitmapとBitmapDescriptorはほぼ同じサイズだと思います。 それは働いた

+0

なぜ1024の代わりに1014?打ち間違え? –

-1

ビットマップを効率的にキャッシュするために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) { } 
      });