谷歌地图精简版模式导致JANK在RecyclerView [英] Google Maps Lite Mode causes jank in RecyclerView

查看:234
本文介绍了谷歌地图精简版模式导致JANK在RecyclerView的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 RecyclerView 这是一个项目一个垂直滚动列表。每个列表项包含了谷歌地图V2图形页面中 精简版模式 。我利用这一新功能,返回的位图,而不是一个完全成熟的地图作为替代来利用谷歌静态地图API

图形页面要求调用的onCreate() onResume()的onPause()的onDestroy()等从父活动/片段的相应方法。哪里是合适的地方调用这些从 RecyclerView.Adapter 和/或 RecyclerView.ViewHolder

我如何清理回收MapViews使记忆力不漏,同时保持列表JANK免费的吗?

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

  

......精简版模式地图选项,非常适合情况下,要   提供多个较小的地图,或者在地图是如此小,以致   有意义的互动是不切实际的,如在一个列表中的缩略图。

ListItem.xml

 < RelativeLayout的的xmlns:机器人=htt​​p://schemas.android.com/apk/res/android
                机器人:layout_width =FILL_PARENT
                机器人:layout_height =FILL_PARENT>

    < com.google.android.gms.maps.MapView
        机器人:ID =@ + ID / mapImageView
        的xmlns:地图=htt​​p://schemas.android.com/apk/res-auto
        机器人:layout_width =80dp
        机器人:layout_height =100dp
        图:liteMode =真
        图:地图类型=正常
        图:cameraZoom =15/>

<  - !...  - >

< / RelativeLayout的>
 

RecyclerView.Adapter和ViewHolder

 公共类NearbyStopsAdapter扩展RecyclerView.Adapter< NearbyStopsAdapter.ViewHolder> {

    私人最终语境mContext;

    公共类ViewHolder扩展RecyclerView.ViewHolder实现View.OnClickListener {

        MapView的地图;

        公共ViewHolder(查看视图){
            超(视图);
            地图=(图形页面)view.findViewById(R.id.mapImageView);
            //如果这在此处产生的?
            map.onCreate(空);
            map.onResume();
        }
    }

    公共NearbyStopsAdapter(上下文C){
        this.mContext = C;
    }

    @覆盖公共ViewHolder onCreateViewHolder(ViewGroup中的ViewGroup,INT位置){
        查看ItemView控件= LayoutInflater.from(viewGroup.getContext())膨胀(R.layout.list_item_nearby_stop,ViewGroup中,假的)。
        返回新ViewHolder(ItemView控件);
    }

    @覆盖公共无效onBindViewHolder(ViewHolder持有人,INT位置){
        //调用异步地图吗?
        holder.map.getMapAsync(本);
    }

    @覆盖公共无效onViewRecycled(ViewHolder持有者){
        //在这里清理的MapView?
//如果(holder.map!= NULL){
// holder.map.onPause();
// holder.map.onDestroy();
//}
    }

    @覆盖公共无效onViewAttachedToWindow(ViewHolder持有者){
        //这里设置的MapView?
// holder.map.onCreate(空);
// holder.map.onResume();
    }

    @覆盖公共无效onViewDetachedFromWindow(ViewHolder持有者){
        //在这里清理的MapView?
//如果(holder.map!= NULL){
// holder.map.onPause();
// holder.map.onDestroy();
//}
    }

    // ...
}
 

logcat的:

  I /谷歌地图Android的API:谷歌播放服务包的版本:659943
W /谷歌地图Android的API:地图加载回调不支持精简版模式
W /谷歌地图Android的API:建筑物中不支持精简版模式
W /谷歌地图Android的API:室内不支持精简版模式
W /谷歌地图Android的API:切换姿态不支持精简版模式
W /谷歌地图Android的API:切换姿态不支持精简版模式
W /谷歌地图Android的API:切换姿态不支持精简版模式
W /谷歌地图Android的API:切换姿态不支持精简版模式
 

解决方案

解决方法如下:

  1. 实施 OnMa preadyCallback ViewHolder 类。
  2. onMa pready ,呼叫 MapsInitializer.initialize ,以garante特征可以得到之前被使用地图。
  

使用这个类来初始化谷歌地图Android的API,如果功能需要得到一张地图前使用。它必须调用因为一些类如BitmapDesc​​riptorFactory和CameraUpdateFactory需要初始化。

<醇开始=3>
  • 回收从地图 onViewRecycled

  •  公共类NearbyStopsAdapter扩展RecyclerView.Adapter&LT; NearbyStopsAdapter.ViewHolder&GT; {
    
    
           @覆盖
           公共无效onBindViewHolder(ViewHolder持有人,INT位置)
           {
              //获取位置从数据清单位置
              //获取的GoogleMap
              GoogleMap的thisMap = holder.gMap;
              //然后将地图移动到位置
              如果(thisMap!= NULL)
                 //将地图移动到位置
                 thisMap.moveCamera(...);
           }
    
    
           //回收的GoogleMap的列表项
           @覆盖
           公共无效onViewRecycled(ViewHolder持有人)
           {
              //在这里清理的MapView?
              如果(holder.gMap!= NULL)
              {
                  holder.gMap.clear();
                  holder.gMap.setMapType(GoogleMap.MAP_TYPE_NONE);
              }
           }
    
    
    
           公共类ViewHolder扩展RecyclerView.ViewHolder实现OnMa preadyCallback {
    
               GoogleMap的GMAP;
               MapView的地图;
                ......
    
               公共ViewHolder(查看视图){
                  超(视图);
                  地图=(图形页面)view.findViewById(R.id.mapImageView);
    
                  如果(图!= NULL)
                  {
                     map.onCreate(空);
                     map.onResume();
                     map.getMapAsync(本);
                  }
    
              }
    
    
              @覆盖
              公共无效onMa pready(GoogleMap的GoogleMap的){
                  //初始化谷歌地图Android的API,如果功能需要得到一张地图前,要使用
                  MapsInitializer.initialize(getApplicationContext());
                  GMAP = GoogleMap的;
    
                  //你可以在这里将地图移动到项目特定的位置
                  INT POS =为getPosition();
                  //获取位置从数据列表POS
                  //然后移动到位置
                  gMap.moveCamera(...);
    
                      ......
             }
    
           }
        }
     

    I have a RecyclerView which is a vertical scrolling list of items. Each list item contains a Google Maps V2 MapView in Lite Mode. I'm taking advantage of this new feature which returns bitmaps instead of a full-blown map as a replacement to the Google Static Maps API.

    MapView requires that you call onCreate(), onResume(), onPause(), onDestroy() etc. from the parent Activity/Fragment's corresponding method. Where is the proper place to call these from the RecyclerView.Adapter and/or RecyclerView.ViewHolder?

    How can I clean up recycled MapViews so that memory doesn't leak, while keeping the list jank free?

    Google says Lite Mode can be used in lists:

    ... ‘lite mode’ map option, ideal for situations where you want to provide a number of smaller maps, or a map that is so small that meaningful interaction is impractical, such as a thumbnail in a list.

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

    解决方案

    Solution as following:

    1. Implement OnMapReadyCallback in ViewHolder class.
    2. In onMapReady, call MapsInitializer.initialize, to garante features can to be used before obtaining a map.

    Use this class to initialize the Google Maps Android API if features need to be used before obtaining a map. It must be called because some classes such as BitmapDescriptorFactory and CameraUpdateFactory need to be initialized.

    1. Recycle map from 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(...);
    
                      ... ...
             }
    
           }
        } 
    

    这篇关于谷歌地图精简版模式导致JANK在RecyclerView的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆