Ich habe eine RecyclerView
, die eine vertikale Scroll-Liste von Elementen ist. Jeder Listeneintrag enthält eine Google Maps V2 MapView in Lite Mode. Ich nutze diese neue Funktion, die Bitmaps statt einer vollwertigen Karte als Ersatz für die Google Static Maps API
zurückgibt.Google Maps Lite-Modus verursacht Jank in RecyclerView
MapView erfordert, dass Sie rufen onCreate()
, onResume()
, onPause()
, onDestroy()
usw. von der übergeordneten Aktivität/Fragment des entsprechenden Verfahrens. Wo ist der richtige Ort, um diese aus der RecyclerView.Adapter
und/oder RecyclerView.ViewHolder
anrufen?
Wie kann ich recycelte MapViews aufräumen, so dass Speicher nicht ausläuft, während die Liste jank frei bleibt?
Google says Lite Mode can be used in lists:
... ‚Lite-Modus‘ Karte Option, ideal für Situationen, in denen Sie eine Reihe von kleineren Karten bieten wollen, oder eine Karte, die so klein ist, dass sinnvolle Interaktion ist nicht praktikabel ist, wie ein Thumbnail in einer Liste.
ListItem.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<com.google.android.gms.maps.MapView
android:id="@+id/mapImageView"
xmlns:map="http://schemas.android.com/apk/res-auto"
android:layout_width="80dp"
android:layout_height="100dp"
map:liteMode="true"
map:mapType="normal"
map:cameraZoom="15"/>
<!-- ... -->
</RelativeLayout>
RecyclerView.Adapter und ViewHolder
public class NearbyStopsAdapter extends RecyclerView.Adapter<NearbyStopsAdapter.ViewHolder> {
private final Context mContext;
public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener {
MapView map;
public ViewHolder(View view) {
super(view);
map = (MapView) view.findViewById(R.id.mapImageView);
// Should this be created here?
map.onCreate(null);
map.onResume();
}
}
public NearbyStopsAdapter(Context c) {
this.mContext = c;
}
@Override public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int position) {
View itemView = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.list_item_nearby_stop, viewGroup, false);
return new ViewHolder(itemView);
}
@Override public void onBindViewHolder(ViewHolder holder, int position) {
//Call Async Map here?
holder.map.getMapAsync(this);
}
@Override public void onViewRecycled(ViewHolder holder) {
// Cleanup MapView here?
// if (holder.map != null) {
// holder.map.onPause();
// holder.map.onDestroy();
// }
}
@Override public void onViewAttachedToWindow(ViewHolder holder) {
// Setup MapView here?
// holder.map.onCreate(null);
// holder.map.onResume();
}
@Override public void onViewDetachedFromWindow(ViewHolder holder) {
// Cleanup MapView here?
// if (holder.map != null) {
// holder.map.onPause();
// holder.map.onDestroy();
// }
}
// ...
}
Logcat:
I/Google Maps Android API﹕ Google Play services package version: 659943
W/Google Maps Android API﹕ Map Loaded callback is not supported in Lite Mode
W/Google Maps Android API﹕ Buildings are not supported in Lite Mode
W/Google Maps Android API﹕ Indoor is not supported in Lite Mode
W/Google Maps Android API﹕ Toggling gestures is not supported in Lite Mode
W/Google Maps Android API﹕ Toggling gestures is not supported in Lite Mode
W/Google Maps Android API﹕ Toggling gestures is not supported in Lite Mode
W/Google Maps Android API﹕ Toggling gestures is not supported in Lite Mode
Update: (3. Februar 2016) Google hat ein Codebeispiel für die Verwendung von Lite Maps in einem ListView veröffentlicht. See here
Ist diese Frage über Ihre RecyclerView nicht glatt oder Garbage Collection eines MapView? Ich glaube nicht, dass diese beiden Probleme eng miteinander verbunden sind. –
Der Jank tritt beim Aufruf von 'getMapAsync (this)' in 'onBindViewHolder (...)' auf, nicht unbedingt auf einem GC. Allerdings wird es auch dort jank sein. –
Verschieben von mapView.onCreate (null); und mapView.getMapAsync (this); von onBindViewHolder zum ViewHolder-Konstruktor hat definitiv eine Menge Jank für mich reduziert. – scottyab