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 Marker
s from it. You can have a class field of type MarkerOptions
for each of your Marker
s and then re-populate the map on configuration changes (for example in onSaveInstanceState
):
mapView.getMap().addMarker(MyMarkerOptions);
Another way would be to save your Marker
s 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.