Google地图精简版模式会在RecyclerView中引起混乱

我有一个RecyclerView这是一个项目的垂直滚动列表。 每个列表项都包含Lite模式下的Google Maps V2 MapView。 我正在利用这个新function,它返回位图,而不是一个完整的地图作为Google Static Maps API的替代品。

MapView要求您从父Activity / Fragment的相应方法调用onCreate()onResume()onPause()onDestroy()等。 从RecyclerView.Adapter和/或RecyclerView.ViewHolder哪里可以调用这些地方?

我如何清理回收的MapViews,使内存不泄漏,同时保持清单免费?

谷歌说精简模式可以在列表中使用:

…'精简模式'的地图选项,非常适合您想要提供一些较小的地图的情况下,或者一个非常小的地图,以至于有意义的交互是不切实际的,比如列表中的缩略图。

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和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 

更新date:(2016年2月3日) Google发布了一个在ListView中使用Lite Maps的代码示例。 看这里

解决scheme如下:

  1. ViewHolder类中实现OnMapReadyCallback
  2. onMapReady ,调用MapsInitializer.initialize ,可以在获取地图之前使用MapsInitializer.initializefunction。

如果在获取地图之前需要使用function,请使用此类来初始化Google Maps Android API。 必须调用它,因为需要初始化BitmapDescriptorFactory和CameraUpdateFactory等类。

  1. onViewRecycled回收地图。

  public class NearbyStopsAdapter extends RecyclerView.Adapter<NearbyStopsAdapter.ViewHolder> { @Override public void onBindViewHolder(ViewHolder holder, int position) { //get 'location' by 'position' from data list //get GoogleMap GoogleMap thisMap = holder.gMap; //then move map to 'location' if(thisMap != null) //move map to the 'location' thisMap.moveCamera(...); } //Recycling GoogleMap for list item @Override public void onViewRecycled(ViewHolder holder) { // Cleanup MapView here? if (holder.gMap != null) { holder.gMap.clear(); holder.gMap.setMapType(GoogleMap.MAP_TYPE_NONE); } } public class ViewHolder extends RecyclerView.ViewHolder implements OnMapReadyCallback { GoogleMap gMap; MapView map; ... ... public ViewHolder(View view) { super(view); map = (MapView) view.findViewById(R.id.mapImageView); if (map != null) { map.onCreate(null); map.onResume(); map.getMapAsync(this); } } @Override public void onMapReady(GoogleMap googleMap) { //initialize the Google Maps Android API if features need to be used before obtaining a map MapsInitializer.initialize(getApplicationContext()); gMap = googleMap; //you can move map here to item specific 'location' int pos = getPosition(); //get 'location' by 'pos' from data list //then move to 'location' gMap.moveCamera(...); ... ... } } } 

查找Google Maps Android API精简版模式示例 ( 源代码 )

Google Map Lite  -  github.com

你需要有一个单独的视图持有人类。 RecyclerView Adapter类将只有onCreateViewHolder()和onBindViewHolder()。

你的布局文件应该看起来像这样:

 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MyActivity"> <view <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> 

onCreate(),onDestroy()将像往常一样在Activity类中被调用。

请按照本教程获得完整的概述。

Google说:

在完全交互模式下使用API​​时,MapView类的用户必须将所有活动生命周期方法转发给MapView类中的相应方法。 生命周期方法的例子包括onCreate(),onDestroy(),onResume()和onPause()。

在lite模式下使用MapView类时,转发生命周期事件是可选的,除了以下情况:

调用onCreate()是强制的,否则不会出现地图。 如果您希望在精简模式映射中显示“我的位置”点,并使用默认的位置源,则需要调用onResume()和onPause(),因为位置源将仅在这些调用之间进行更新。 如果您使用自己的位置来源,则无需调用这两种方法。

所以在lite模式下,您不必担心onDestroy(),onResume()和onPause()

我已经删除了这个Override方法,因为每次在testing时这会给出空的映射,并且它在我的recyclerView中完美地工作。

 @Override public void onViewRecycled(ViewHolder holder) { // Cleanup MapView here? if (holder.gMap != null) { holder.gMap.clear(); holder.gMap.setMapType(GoogleMap.MAP_TYPE_NONE); } } 

如果上面的代码在你的情况下不起作用,你可以试试。