The disadvantage of Google Maps v2 after returning their fragment from the stack

I have an Activity with a MapFragment , which I programmatically add to the Activity using FragmentTransaction :

 private static final String MAP_FRAGMENT_TAG = "map"; private MapFragment mapFragment = null; ... protected void onCreate(Bundle savedInstanceState) { ... mapFragment = (MapFragment) getFragmentManager().findFragmentByTag(MAP_FRAGMENT_TAG); if (mapFragment == null) { mapFragment = MapFragment.newInstance(); FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction(); fragmentTransaction.add(R.id.fragment_wrapper, mapFragment, MAP_FRAGMENT_TAG); fragmentTransaction.commit(); } ... } 

The standard way. Then I get an instance of GoogleMap from MapFragment and set its settings, install listeners, do everything with it. Everything is working fine.

Then, when the user is done with the map, AsyncTask appears to show the ProgressDialog , perform some operation, put another fragment in fragment_wrapper and release the ProgressDialog again:

 private class GetFlightsTask extends AsyncTask<Double, Void, String> { @Override protected void onPreExecute() { super.onPreExecute(); // the activity context has been passed to the AsyncTask through its constructor loadingFlightsSpinner = new ProgressDialog(context); // setting the dialog up loadingFlightsSpinner.show(); } @Override protected String doInBackground(Double... params) { // some pretty long remote API call // (loading a JSON file from http://some.website.com/...) } @Override protected void onPostExecute(String flightsJSON) { super.onPostExecute(flightsJSON); // here I do stuff with the JSON and then I swtich the fragments like this FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction(); FlightsFragment fragment = new FlightsFragment(); fragmentTransaction.replace(R.id.fragment_wrapper, fragment); fragmentTransaction.addToBackStack(null); fragmentTransaction.commit(); loadingFlightsSpinner.dismiss(); } 

Everything is still working fine. The user does something in FlightsFragment , and then maybe decides to return to the map. Presses the back button and the map reappears. And this is when the card becomes broken. The names of countries / cities on it load very slowly, they lag far behind moving the map ... And I have no idea why, I do nothing when you click MapFragment back.

Interestingly, it is fixed, for example, by pressing the "home" button, and then returns to the application again ...

What am I doing wrong?

Thanks for any ideas.

+6
source share
3 answers

I fixed this by rejecting the ProgressDialog at the end of the AsyncTask doInBackground() method, and not at the beginning of the onPostExecute() method.

This is a bit weird because I actually thought I shouldn't touch things from the user interface in the doInBackground() method ... If someone wants to figure this out a bit, I would be happy to know why it works, how is it .

+1
source

Does it only fall behind if you click the back button?

If this is a problem, try locking the back button or exit the application, try this code:

  @Override public void onBackPressed(){ AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setMessage("You wanna leave the aplication?").setPositiveButton("Yes", dialogClickListener) .setNegativeButton("No", dialogClickListener).show(); } 

or try this code to put a map fragment in another fragment (a nested map fragment), it worked for me a few weeks ago:

Java class:

 public class Yourfragment extends Fragment { private MapView mMapView; private GoogleMap mMap; private Bundle mBundle; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View inflatedView = inflater.inflate(R.layout.map_fragment, container, false); try { MapsInitializer.initialize(getActivity()); } catch (GooglePlayServicesNotAvailableException e) { // TODO handle this situation } mMapView = (MapView) inflatedView.findViewById(R.id.map); mMapView.onCreate(mBundle); setUpMapIfNeeded(inflatedView); return inflatedView; } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mBundle = savedInstanceState; } private void setUpMapIfNeeded(View inflatedView) { if (mMap == null) { mMap = ((MapView) inflatedView.findViewById(R.id.map)).getMap(); if (mMap != null) { setUpMap(); } } } private void setUpMap() { mMap.addMarker(new MarkerOptions().position(new LatLng(0, 0)).title("Marker")); } @Override public void onResume() { super.onResume(); mMapView.onResume(); } @Override public void onPause() { super.onPause(); mMapView.onPause(); } @Override public void onDestroy() { mMapView.onDestroy(); super.onDestroy(); } } 

XML:

 <com.google.android.gms.maps.MapView android:id="@+id/map" android:layout_width="match_parent" android:layout_height="match_parent" /> 

put this code in post execute:

 View inflatedView = inflater.inflate(R.layout.map_fragment, container, false); try { MapsInitializer.initialize(getActivity()); } catch (GooglePlayServicesNotAvailableException e) { // TODO handle this situation } mMapView = (MapView) inflatedView.findViewById(R.id.map); mMapView.onCreate(mBundle); setUpMapIfNeeded(inflatedView); return inflatedView; 

and call assynctask on oncreateview

Try the following:

 public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { //Call assyncTask } @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); mBundle = savedInstanceState; } private void setUpMapIfNeeded(View inflatedView) { if (mMap == null) { mMap = ((MapView) inflatedView.findViewById(R.id.map)).getMap(); if (mMap != null) { setUpMap(); } } } private void setUpMap() { mMap.addMarker(new MarkerOptions().position(new LatLng(0, 0)).title("Marker")); } @Override public void onResume() { super.onResume(); mMapView.onResume(); } @Override public void onPause() { super.onPause(); mMapView.onPause(); } @Override public void onDestroy() { mMapView.onDestroy(); super.onDestroy(); } private class GetFlightsTask extends AsyncTask<Double, Void, String> { @Override protected void onPreExecute() { super.onPreExecute(); // if I remove the next line, everything gets fixed loadingFlightsSpinner.show(); } @Override protected String doInBackground(Double... params) { // some pretty long remote API call // (loading a JSON file from http://some.website.com/flights?...) // works fine String flightsJSON = loadJSON("flights?flyFrom=CZ&to=..."); } @Override protected void onPostExecute(String flightsJSON) { super.onPostExecute(flightsJSON); loadingFlightsSpinner.dismiss(); // here I do stuff with the JSON and then replace the fragment dohardwork() } public view dohardwork(){ View inflatedView = inflater.inflate(R.layout.map_fragment, container, false); try { MapsInitializer.initialize(getActivity()); } catch (GooglePlayServicesNotAvailableException e) { // TODO handle this situation } mMapView = (MapView) inflatedView.findViewById(R.id.map); mMapView.onCreate(mBundle); setUpMapIfNeeded(inflatedView); return inflatedView; } 
+2
source

I missed a simple test:

 public class MapFragmentOnBackStackExample extends FragmentActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.map_fragment_on_back_stack_example); FragmentManager fm = getSupportFragmentManager(); Fragment f = fm.findFragmentById(R.id.fragment_container); if (f == null) { f = SupportMapFragment.newInstance(); FragmentTransaction transaction = fm.beginTransaction(); transaction.add(R.id.fragment_container, f); transaction.commit(); } } public void onAddFragmentClick(View view) { FragmentManager fm = getSupportFragmentManager(); FragmentTransaction transaction = fm.beginTransaction(); transaction.replace(R.id.fragment_container, new MyFragment()); transaction.addToBackStack(null); transaction.commit(); } public static class MyFragment extends Fragment { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { TextView textView = new TextView(getActivity()); textView.setText("MyFragment: " + hashCode()); return textView; } } } 

and does not see any problems.

I could see the problem with the comments if (f == null) { , leaving it to always create a new fragment during rotation, which is obviously incorrect, but causes some suspicion.

Can you see more than one MapFragment in memory at a time? Try using the Eclipse Memory Analyzer (MAT).

+1
source

Source: https://habr.com/ru/post/943825/


All Articles