Issue
I have a use case where a list and a map view share quite the same code base and show the same data. So I cannot separate them by using ListFragment and MapFragment as parent.
So I made a fragment that contains both views:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="@+id/list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:visibility="invisible"/>
<com.google.android.gms.maps.MapView
android:id="@+id/mapView"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</RelativeLayout>
The user can toggle between list and map view. This works very well despite the fact that the map view cannot retain its markers on configuration changes. When the screen is rotated, the map view get's its initial state without markers and without zoom. All markers that where previously added are gone. When I used MapFragment I did not have this problem, it kind of retained itself.
Stripped down code:
public class ListAndMapFragment extends Fragment {
private MapView mapView;
public ListAndMapFragment() {}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setRetainInstance(true);
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle arguments) {
super.onCreateView(inflater, container, arguments);
View root = inflater.inflate(R.layout.fragment_pillar_list, container, false);
mapView = (MapView) root.findViewById(R.id.mapView);
if (arguments == null) {
mapView.onCreate(null);
MapsInitializer.initialize(this.getActivity());
}
return root;
}
private GoogleMap getMap() {
return mapView.getMap();
}
@Override
public void onResume() {
mapView.onResume();
super.onResume();
}
@Override
public void onDestroy() {
super.onDestroy();
mapView.onDestroy();
}
@Override
public void onLowMemory() {
super.onLowMemory();
mapView.onLowMemory();
}
}
Any ideas how to address this problem? One solution would be to replace all markers. However I would like to know if there is another approach.
Solution
Marker object cannot be retained through configuration changes because it doesn't implement Parcelable or Serializable interface.
However, you can persist MarkerOptions object because it is Parcelable and then recreate your Markers from it. You can have a class field of type MarkerOptions for each of your Markers and then re-populate the map on configuration changes (for example in onSaveInstanceState):
mapView.getMap().addMarker(MyMarkerOptions);
Another way would be to save your Markers in a HashMap and re-use them on configuration changes.
Here is another full example that uses Parcelable LatLng points to persist Markers.
The example works so when adding a marker it also adds the corresponding coordinates to an ArrayList as LatLng object. Then on configuration change, the ArrayList gets saved to a Bundle object in onSaveInstanceState and the LatLng objects get retrieved in onCreate.
OP's note:
So I went with the solution to implement onSaveInstanceState and drop setRetainInstance(true). The benefit is that I can retain the map myself. However the disadvantage is that the map has to be fully initialized on each config change which makes the app slow for 1 or 2 seconds on e.g. screen rotation. But I am fine with this.
Answered By - nem035
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.