4

I have used map view inside recyclerview row. I have attached screenshot. While scrolling maps display black flickering background.

check my screenshot

Adapter code:

 @Override
    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
        if (viewType == TASK_VIEW) {
            return new TasksViewHolder(LayoutInflater.from(parent.getContext())
                    .inflate(R.layout.item_task_row, parent, false));
        } else if (viewType == CHECKIN_VIEW) {
            return new CheckInViewHolder(LayoutInflater.from(parent.getContext())
                    .inflate(R.layout.item_checkin_row, parent, false));
        } else {
            return null;
        }
    }


@Override
private void onBindCheckInViewHolder(CheckInViewHolder holder, int position) {
    final JobCheckIn singleCheckIn = (JobCheckIn) items.get(position);
    holder.location.setText(singleCheckIn.getAddress());

    holder.lastUpdated.setText(String.valueOf("Created " +
            activity.getDateTime(singleCheckIn.getCreatedDateTime())));

    holder.deleteTask.setOnClickListener(view -> jobInterface.deleteCheckIn(singleCheckIn.getId()));

    float f = 0.0f;
    if (holder.mapView != null && Float.compare(singleCheckIn.getLatitude(), f) != 0 &&
            Float.compare(singleCheckIn.getLongitude(), f) != 0) {
        holder.mapView.setVisibility(View.VISIBLE);
        holder.initializeMapView();
        if (holder.gMap != null) {
            // The map is already ready to be used
            moveMap(holder.gMap, singleCheckIn.getLatitude(), singleCheckIn.getLongitude());
        }
    }

}
   public class CheckInViewHolder extends RecyclerView.ViewHolder implements OnMapReadyCallback {

    MapView mapView;

    GoogleMap gMap;


    public CheckInViewHolder(View view) {
        super(view);
        mapView = view.findViewById(R.id.checkInMapView);

    }


    @Override
    public void onMapReady(GoogleMap googleMap) {
        MapsInitializer.initialize(context);
        gMap = googleMap;
        googleMap.getUiSettings().setMapToolbarEnabled(false);
        if(items.get(getLayoutPosition())!=null )
            moveMap(gMap,((JobCheckIn) items.get(getLayoutPosition())).getLatitude(), ((JobCheckIn) items.get(getLayoutPosition())).getLongitude());
    }
    public void initializeMapView() {
        if (mapView != null) {
            // Initialise the MapView
            mapView.onCreate(null);
            // Set the map ready callback to receive the GoogleMap object
            mapView.getMapAsync(this);

        }
    }
}
 public void moveMap(GoogleMap gMap, double latitude, double longitude) {
    Log.v(TAG, "mapMoved: " + gMap);
    LatLng latlng = new LatLng(latitude, longitude);
    CameraUpdate cu = CameraUpdateFactory.newLatLngZoom(latlng, 6);
    gMap.addMarker(new MarkerOptions().position(latlng));
    gMap.moveCamera(cu);
}

I refer this link: Link but in this demo they used array adapter in my code we have used recyclerview adapter.

xml code:

 <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="150dp">

            <com.google.android.gms.maps.MapView
                android:id="@+id/checkInMapView"
                android:layout_width="0dp"
                android:layout_height="150dp"
                android:layout_weight="1"
                android:enabled="true"
                android:visibility="gone"
                map:cameraZoom="15"
                map:liteMode="true"
                map:mapType="normal" />

         <!--   I have also tried adding transparent view as below but still no solution.

        <View
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:background="@android:color/transparent"/>-->

        </LinearLayout>

I am not performing any zoom-In, Zoom-out or drag. Thanks in advance.

Google Issue Track


Update

Previously i was initializing map in viewHolder instead of mentioned as above scenario.

 onBindCheckInViewHolder(...){
 holder.mapView.onCreate(null);
            holder.mapView.getMapAsync(googleMap -> {
                MapsInitializer.initialize(context);
                gMap = googleMap;
                googleMap.getUiSettings().setMapToolbarEnabled(false);
                moveMap(gMap, singleCheckIn.getLatitude(), singleCheckIn.getLongitude());
            });
      }
Grishma Ukani
  • 636
  • 5
  • 16
  • Maps are a bit special, it needs to be initialized and have a bit of time so you don't see that flicker, see [this gist](https://gist.github.com/alunsford3/5d7c1bb5a67b90b4e1f3) for inspiration – elmorabea Dec 05 '17 at 10:00
  • @elmorabea but every time we scroll in recyclerview, it updates its entire view holder plus as you can see in my code, i am using multiple view type. – Grishma Ukani Dec 05 '17 at 10:29
  • Views and view holders are bound again when scrolling, but they are not re-created. So if the view is initialized, and being recycled, and you bind it to new data. – elmorabea Dec 05 '17 at 10:32
  • Inside RecyclerViewMapViewAdapter.java class of that link onCreateViewHolder method mMapViewListItemViews.add(mapViewListItemView); mMapViewListItemViews this field is not declared. – Grishma Ukani Dec 05 '17 at 10:43
  • @elmorabea can you please suggest me in my code what i have to do? – Grishma Ukani Dec 05 '17 at 11:07
  • Can you just for testing purposes, move map initialization code to the ViewHolder constructor, instead of onBindViewHolder? – elmorabea Dec 05 '17 at 11:13
  • @elmorabea please check my update. Previously i was using that updated code into onBindViewHolderitsself. – Grishma Ukani Dec 05 '17 at 11:24
  • @ Grishma Ukani Check my answer please, and let's chat if you have questions – elmorabea Dec 05 '17 at 12:52
  • 1
    @elmorabea I will do this tomorrow and if i have questions will ask you. i can't move into chat.. will ask you here only.i'm just upvoting your answer. Tomorrow will try and let you know. Thanks for the effort. – Grishma Ukani Dec 05 '17 at 12:58

4 Answers4

4

Write this line in AndroidManifest.xml:

android:hardwareAccelerated="true"
 <application
        android:name="com.xyz"
        android:allowBackup="true"
        android:hardwareAccelerated="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:largeHeap="true"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
</application>

It works.

Pang
  • 9,564
  • 146
  • 81
  • 122
rizwan
  • 164
  • 2
  • 5
  • *This flag is turned on by default for applications that are targeting `ICE_CREAM_SANDWICH` or later.* So if you are reading this in 2019 or later, this answer probably doesn't apply to you. – arekolek Jul 02 '19 at 20:01
2

So I dug around a bit, and here are some suggestions to make the performance a little better, it's not perfect, but it is a lot faster.

Map type

This basically determines how the map looks like (normal/hybrid... etc), you need to set the map type to GoogleMap.MAP_TYPE_NONE in these cases.

  • XML where you define the view, so this is the default type
  • Override onViewRecycled in your adapter and if your holder has a GoogleMap set its type to none

Only set your type back to GoogleMap.MAP_TYPE_NORMAL or whatever type you want, when your onBindViewHolder is called.

Pre-initialization

Call MapsInitializer.initialize(context) from your onMapReady callback.

Initialization

Call GoogleMap.onCreate() and GoogleMap.getMapAsync() from your onCreateViewHolder, maybe in your ViewHolder constructor.

RecyclerView Prefetch

You can also use a neat new feature of LinearLayoutManager, you can call LinearLayoutManager.setInitialPrefetchItemCount, to start preparing off screen items.

Not that this can cause other performance issues, tweak it till you get a nice balance.

Optimize layout

  • Try to have the layout where your RecyclerView to be flat as possible, don't nest too much layouts
  • Make sure you set setHasFixedSize(true) for your RecyclerView
  • Make sure to avoid weights or RelativeLayouts as parents of your RecyclerView or your children list items.
Aks4125
  • 4,522
  • 4
  • 32
  • 48
elmorabea
  • 3,243
  • 1
  • 14
  • 20
  • hi, there is null pointer exception in onViewRecycycled method where i am setting map type. Gmap is null. @Override public void onViewRecycled(RecyclerView.ViewHolder holder) { super.onViewRecycled(holder); if(gMap!=null) gMap.setMapType(GoogleMap.MAP_TYPE_NONE); } – Grishma Ukani Dec 06 '17 at 05:17
  • Well, you need to check if googleMap object is not null, and if it is not null (means the recycler view had a chance to getMapAsync) you set its type to NONE – elmorabea Dec 06 '17 at 08:38
  • Use the chat https://chat.stackoverflow.com/rooms/160507/discussion-between-grishma-ukani-and-elmorabea – elmorabea Dec 06 '17 at 09:29
2
<application
    android:name="com.yourpackagename"
    android:allowBackup="true"
    android:hardwareAccelerated="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:largeHeap="true"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">

Just add hardwareAccelerated as True in your Project Manifest file

Satya
  • 21
  • 2
  • *This flag is turned on by default for applications that are targeting `ICE_CREAM_SANDWICH` or later.* – arekolek Jul 02 '19 at 20:02
0

MapView is a pretty heavy view and when you try to get a bunch of them on the screen then app will become sluggish while scrolling. you can pass data such as the latitude and longitude as a string with some static variables taken from the link mentioned below. you can get co-ordinates from the Facebook API. This is the api link https://developers.google.com/maps/documentation/staticmaps/.

 String getMapURL = "http://maps.googleapis.com/maps/api/staticmap?zoom=
                    18&size=560x240&markers=size:mid|color:red|"  
                    + JOLocation.getString("latitude") + "," + JOLocation.getString("longitude")
                    + "&sensor=false";

The above constructed URL, when you used in a browser, returns a .PNG file. Similar type of issue was discussed here in this link MapView in Listview check it. Hope it helps

anand krish
  • 4,281
  • 4
  • 44
  • 47