Android 谷歌地图Lite模式在RecyclerView中引起jank
我有一个Android 谷歌地图Lite模式在RecyclerView中引起jank,android,google-maps,android-recyclerview,google-play-services,google-maps-lite,Android,Google Maps,Android Recyclerview,Google Play Services,Google Maps Lite,我有一个RecyclerView,它是一个项目的垂直滚动列表。每个列表项中都包含一个Google Maps V2地图视图。我正在利用这个新功能,它返回位图而不是完整的位图,以替代谷歌静态地图API 需要从父活动/片段的相应方法调用onCreate()、onResume()、onPause()、onDestroy()等。从RecyclerView.Adapter和/或RecyclerView.ViewHolder调用这些的正确位置在哪里 如何清理回收的地图视图,使内存不会泄漏,同时保持列表的自由
RecyclerView
,它是一个项目的垂直滚动列表。每个列表项中都包含一个Google Maps V2地图视图。我正在利用这个新功能,它返回位图而不是完整的位图,以替代谷歌静态地图API
需要从父活动/片段的相应方法调用onCreate()
、onResume()
、onPause()
、onDestroy()
等。从RecyclerView.Adapter
和/或RecyclerView.ViewHolder
调用这些的正确位置在哪里
如何清理回收的地图视图,使内存不会泄漏,同时保持列表的自由
…'lite mode“映射选项,非常适合您需要
提供一些较小的地图,或一个小到
有意义的交互是不切实际的,例如列表中的缩略图
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>
更新:(2018年6月8日)谷歌发布了一个在列表视图中使用Lite地图的代码示例 您需要有一个单独的视图持有者类。RecyclerView适配器类只有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>
解决方案如下:
在ViewHolder
类中执行OnMapReadyCallback
在onMapReady
中,调用mapsitializer.initialize
,以确保在获取地图之前可以使用这些功能
如果在获取地图之前需要使用功能,请使用此类初始化Google Maps Android API。必须调用它,因为某些类(如BitmapDescriptorFactory和CameraUpdateFactory)需要初始化
从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(...);
... ...
}
}
}
公共类NearbyStopsAdapter扩展了RecyclerView.Adapter{
@凌驾
公共无效onBindViewHolder(ViewHolder,int位置)
{
//通过数据列表中的“位置”获取“位置”
//获取谷歌地图
谷歌地图thisMap=holder.gMap;
//然后将地图移动到“位置”
if(thisMap!=null)
//将地图移动到“位置”
这张地图。移动相机(…);
}
//为列表项回收GoogleMap
@凌驾
视图上的公共无效已回收(视图持有人)
{
//这里是地图视图吗?
如果(holder.gMap!=null)
{
holder.gMap.clear();
holder.gMap.setMapType(GoogleMap.MAP\u TYPE\u无);
}
}
公共类ViewHolder扩展了RecyclerView.ViewHolder在MapReadyCallback上实现{
谷歌地图;
地图视图;
... ...
公共视图持有者(视图){
超级(视图);
map=(MapView)view.findViewById(R.id.mapImageView);
if(map!=null)
{
map.onCreate(null);
onResume();
getMapAsync(this);
}
}
@凌驾
4月1日公开作废(谷歌地图谷歌地图){
//如果在获取地图之前需要使用功能,请初始化Google Maps Android API
初始化(getApplicationContext());
gMap=谷歌地图;
//您可以将此地图移动到特定于项目的“位置”
int pos=getPosition();
//通过数据列表中的“pos”获取“位置”
//然后移动到“位置”
移动摄影机(…);
... ...
}
}
}
谷歌说:
在完全交互模式下使用API时,MapView类的用户必须将所有活动生命周期方法转发给MapView类中的相应方法。生命周期方法的示例包括onCreate()、onDestroy()、onResume()和onPause()
在lite模式下使用MapView类时,转发生命周期事件是可选的,但以下情况除外:
必须调用onCreate(),否则将不显示映射。
如果希望在lite模式映射上显示“我的位置”点并使用默认位置源,则需要调用onResume()和onPause(),因为位置源只会在这些调用之间更新。如果使用自己的位置源,则无需调用这两个方法
因此,在lite模式下,您不必担心onDestroy()、onResume()和onPause()查找()
我已经删除了这个覆盖方法,因为每次测试时它都会给出空映射,并且它在我的recyclerView中工作得非常好
@Override
public void onViewRecycled(ViewHolder holder)
{
// Cleanup MapView here?
if (holder.gMap != null)
{
holder.gMap.clear();
holder.gMap.setMapType(GoogleMap.MAP_TYPE_NONE);
}
}
如果上述代码在您的情况下不起作用,您可以尝试使用它。谷歌地图提供Lite模式
Android版地图SDK可以提供地图的位图图像,为用户提供有限的交互性。这称为精简模式映射
遵循:使用lite模式在ListView中高效显示地图的示例。我想您可能没有回答这个问题。RecyclerView.Adapter
中已经定义了一个ViewHolder。问题是应该在何处调用MapView.onCreate()
,MapView.onDestroy()
等?请查看布局文件“代码”下方的行,活动类中将一如既往地调用onCreate(),onDestroy()。“您的链接不包括MapView
。”。它有什么关系?这是通常的活动课。。。使用onCreate()和描述的其他Android生命周期方法。有关更多详细信息,请参阅这段代码,其中包含mapView和从布局充气器中提取的数据,RecyclerView
没有onCreate()
和其他Android生命周期方法。以及RecyclerView
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(...);
... ...
}
}
}
@Override
public void onViewRecycled(ViewHolder holder)
{
// Cleanup MapView here?
if (holder.gMap != null)
{
holder.gMap.clear();
holder.gMap.setMapType(GoogleMap.MAP_TYPE_NONE);
}
}