Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Retrieve map state while switching between fragments #26

Closed
AryaRDI opened this issue Sep 8, 2016 · 9 comments
Closed

Retrieve map state while switching between fragments #26

AryaRDI opened this issue Sep 8, 2016 · 9 comments

Comments

@AryaRDI
Copy link

AryaRDI commented Sep 8, 2016

hi guys,

i need a hand about this issue, im using NavigationDrawer in my code and every time user choose an item from:
onNavigationItemSelected(MenuItem item) a fragment will be loaded, 1 have a fragment which i implemented a map inside with some markers and clusters the problem is when the user go to another fragment and he comeback again to the fragment with map all these markers and clusters going to be generated again and it makes the app really slow what you suggest for it?

MainActivity:

    public class MainActivity extends AppCompatActivity
        implements NavigationView.OnNavigationItemSelectedListener {

    NavigationView navigationView = null;
    Toolbar toolbar = null;
    GoogleMap nMap;
    SparseArray<Fragment> myFragments;
    JSONArray jArray;
    private static final int ERROR_DIALOG_REQUEST = 9001;
    public static final int ID_OF_BEACH = 5;
    //initBeach test = new initBeach();
    //JSONArray jsonArray = test.ExcuteLoad();

    /**
     * ATTENTION: This was auto-generated to implement the App Indexing API.
     * See https://g.co/AppIndexing/AndroidStudio for more information.
     */
    private GoogleApiClient client;
    Fragment fragment;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        myFragments = new SparseArray<>();

        //setTitle("");
        setContentView(R.layout.activity_main);

        if (servicesOK()) {
            try {
                jArray = new LoadJson().execute().get();
            } catch (Exception e) {
                e.printStackTrace();
            }
        } else {
            setContentView(R.layout.activity_main);
        }

        //Set the fragment initially
        FragmentTransaction fragmentTransaction =
                getSupportFragmentManager().beginTransaction();
        fragmentTransaction.replace(R.id.fragment_container, new MainFragment(jArray));
        fragmentTransaction.addToBackStack("1");
        fragmentTransaction.commit();

        toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);
        //noinspection ConstantConditions
        getSupportActionBar().setDisplayShowTitleEnabled(false);


        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);

        ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
                this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
        drawer.setDrawerListener(toggle);
        toggle.syncState();


        navigationView = (NavigationView) findViewById(R.id.nav_view);

        //How to change elements in the header programatically


        navigationView.setNavigationItemSelectedListener(this);
        // ATTENTION: This was auto-generated to implement the App Indexing API.
        // See https://g.co/AppIndexing/AndroidStudio for more information.
        client = new GoogleApiClient.Builder(this).addApi(AppIndex.API).build();
        navigationView.setItemIconTintList(null);

    }

    @Override
    public void onBackPressed() {
        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
        if (drawer.isDrawerOpen(GravityCompat.START)) {
            drawer.closeDrawer(GravityCompat.START);
        } else {
            super.onBackPressed();
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        //noinspection SimplifiableIfStatement
        return super.onOptionsItemSelected(item);
    }


    @Override
    public boolean onNavigationItemSelected(MenuItem item) {
        // Handle navigation view item clicks here.
        int id = item.getItemId();

        if (id == R.id.nav_camara) {
            fragment = myFragments.get(1);
            // if fragment doesn't exist in myFragments, create one and add to it
            if (fragment == null) {
                fragment = new MainFragment(jArray);
                myFragments.put(1, fragment);
            }
            FragmentTransaction fragmentTransaction =
                    getSupportFragmentManager().beginTransaction();
            fragmentTransaction.replace(R.id.fragment_container, fragment);
            fragmentTransaction.commit();


            // Handle the camera actionn

        } else if (id == R.id.nav_gallery) {
            //Set the fragment initially
            fragment = myFragments.get(2);
            // if fragment doesn't exist in myFragments, create one and add to it
            if (fragment == null) {
                fragment = new GalleryFragment();
                myFragments.put(2, fragment);
            }

            FragmentTransaction fragmentTransaction =
                    getSupportFragmentManager().beginTransaction();
            fragmentTransaction.replace(R.id.fragment_container, fragment);
            fragmentTransaction.commit();


        } else if (id == R.id.nav_search) {
            //Set the fragment initially

            // Handle the camera action

        } else if (id == R.id.nav_manage) {

            // Handle the camera action

        } else if (id == R.id.nav_share) {

        } else if (id == R.id.nav_send) {

        }

        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
        drawer.closeDrawer(GravityCompat.START);
        return true;
    }

    public boolean servicesOK() {

        int isAvailable = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);

        if (isAvailable == ConnectionResult.SUCCESS) {
            return true;
        } else if (GooglePlayServicesUtil.isUserRecoverableError(isAvailable)) {
            Dialog dialog =
                    GooglePlayServicesUtil.getErrorDialog(isAvailable, this, ERROR_DIALOG_REQUEST);
            dialog.show();
        } else {
            Toast.makeText(this, "Can't connect to mapping service", Toast.LENGTH_SHORT).show();
        }

        return false;
    }


    @Override
    public void onStart() {
        super.onStart();

        // ATTENTION: This was auto-generated to implement the App Indexing API.
        // See https://g.co/AppIndexing/AndroidStudio for more information.
        client.connect();
        Action viewAction = Action.newAction(
                Action.TYPE_VIEW, // TODO: choose an action type.
                "Main Page", // TODO: Define a title for the content shown.
                // TODO: If you have web page content that matches this app activity's content,
                // make sure this auto-generated web page URL is correct.
                // Otherwise, set the URL to null.
                Uri.parse("http://host/path"),
                // TODO: Make sure this auto-generated app URL is correct.
                Uri.parse("android-app://com.compscitutorials.basigarcia.navigationdrawervideotutorial/http/host/path")
        );
        AppIndex.AppIndexApi.start(client, viewAction);
    }

    @Override
    public void onStop() {
        super.onStop();

        // ATTENTION: This was auto-generated to implement the App Indexing API.
        // See https://g.co/AppIndexing/AndroidStudio for more information.
        Action viewAction = Action.newAction(
                Action.TYPE_VIEW, // TODO: choose an action type.
                "Main Page", // TODO: Define a title for the content shown.
                // TODO: If you have web page content that matches this app activity's content,
                // make sure this auto-generated web page URL is correct.
                // Otherwise, set the URL to null.
                Uri.parse("http://host/path"),
                // TODO: Make sure this auto-generated app URL is correct.
                Uri.parse("android-app://com.compscitutorials.basigarcia.navigationdrawervideotutorial/http/host/path")
        );
        AppIndex.AppIndexApi.end(client, viewAction);
        client.disconnect();
    }


    //AsyincTask to load JSON
    public class LoadJson extends AsyncTask<String, Void, JSONArray> {
        String URLu = "http://www.meteoapps.com/appvalenciaplayas/playaslocales";


        @Override
        protected JSONArray doInBackground(String... params) {

            try {
                URL url = new URL(URLu);
                HttpURLConnection connection = (HttpURLConnection) url.openConnection();
                connection.connect();
                InputStream stream = connection.getInputStream();
                BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
                StringBuffer buffer = new StringBuffer();
                String line = "";
                while ((line = reader.readLine()) != null) {
                    buffer.append(line);
                }
                String finalJson = buffer.toString();

                JSONObject jsonObject = new JSONObject(finalJson);
                JSONArray jsonArray = jsonObject.getJSONArray("marcadores");

                return jsonArray;
            } catch (Exception e) {
                e.printStackTrace();
                return null;
            }

        }

        @Override
        protected void onPostExecute(JSONArray result) {
            super.onPostExecute(result);
        }

        @Override
        protected void onPreExecute() {
          super.onPreExecute();
        }

       }
    }

MainFragment:

public class MainFragment extends Fragment {
GoogleMap nMap;
MapView mapView;
CameraUpdate update;
JSONArray array;
private ClusterManager<ItemCluster> mClusterManager;
private void parseJSON(JSONArray array) {
    if (mapView != null) {
        nMap = mapView.getMap();
        nMap.getUiSettings().setMyLocationButtonEnabled(false);
        nMap.setMyLocationEnabled(true);
        nMap.getUiSettings().setZoomControlsEnabled(true);
        mClusterManager = new ClusterManager<>(this.getActivity(), nMap);
        nMap.setOnCameraChangeListener(mClusterManager);
        nMap.setInfoWindowAdapter(mClusterManager.getMarkerManager());
        nMap.setOnMarkerClickListener(mClusterManager);
    }

    try {
        //Loading LAT LOng of markers on map
        for (int i = 0; i < array.length(); i++) {
            JSONObject jsonObject = array.getJSONObject(i);
            String locality = jsonObject.getString("nombre");
            String vientos = jsonObject.getString("viento");
            int temp = jsonObject.getInt("temperatura");
            double lat = jsonObject.getDouble("lat");
            double lon = jsonObject.getDouble("lon");
            nMap = mapView.getMap();

            mClusterManager.setRenderer(new OwnIconRendered(getActivity().getApplicationContext(), nMap, mClusterManager));
            ItemCluster offsetItem = new ItemCluster(lat, lon, locality, vientos, temp);
            mClusterManager.addItem(offsetItem);
        }
        LatLng latLon = new LatLng(39.4666667, -0.3666667);
        update = CameraUpdateFactory.newLatLngZoom(latLon, 10);
        nMap.moveCamera(update);

    } catch (Exception e) {
        e.printStackTrace();
    }

}

@SuppressLint("ValidFragment")
public MainFragment(JSONArray input) {
    array = input;
}
public MainFragment() {

}



@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {

    View rootView = inflater.inflate(R.layout.fragment_main, container, false);
    mapView = (MapView) rootView.findViewById(R.id.map);
    mapView.onCreate(savedInstanceState);

    parseJSON(array);

    // Inflate the layout for this fragment
    setRetainInstance(true);
    return rootView;

}

class OwnIconRendered extends DefaultClusterRenderer<ItemCluster> {

    private final IconGenerator mClusterIconGenerator = new IconGenerator(getActivity().getApplicationContext());
    private final TextView mClusterImageView;
    private final ImageView mClusterViento;
    private int tempAvg = 0;
    private final Drawable TRANSPARENT_DRAWABLE = new ColorDrawable(Color.TRANSPARENT);


    public OwnIconRendered(Context context, GoogleMap map,
                           ClusterManager<ItemCluster> clusterManager) {
        super(context, map, clusterManager);

        View clusterIcon = getActivity().getLayoutInflater().inflate(R.layout.info_windows, null);
        mClusterIconGenerator.setContentView(clusterIcon);
        mClusterImageView = (TextView) clusterIcon.findViewById(R.id.maxTmp);
        mClusterViento = (ImageView) clusterIcon.findViewById(R.id.viento);

    }

    @Override
    protected void onBeforeClusterItemRendered(ItemCluster item, MarkerOptions markerOptions) {
        markerOptions.icon(BitmapDescriptorFactory.fromResource(R.drawable.marcador_playa));
        markerOptions.title(item.getTitle());
        super.onBeforeClusterItemRendered(item, markerOptions);
    }

    @Override
    protected void onBeforeClusterRendered(Cluster<ItemCluster> cluster, MarkerOptions markerOptions) {

        tempAvg = 0;
        String vientoStr = null;
        for (ItemCluster item : cluster.getItems()) {
            tempAvg = (item.getTemp()+tempAvg);
        }

        mClusterImageView.setText(String.valueOf(tempAvg/cluster.getSize()));
        if ((tempAvg/cluster.getSize()) > 32) {
            mClusterImageView.setBackgroundResource(R.drawable.temp_32_o_mas);
        } else if ((tempAvg/cluster.getSize()) <= 31 && (tempAvg/cluster.getSize()) >= 25) {
            mClusterImageView.setBackgroundResource(R.drawable.temp_25_a_31);
        } else if ((tempAvg/cluster.getSize()) <= 24 && (tempAvg/cluster.getSize()) >= 20) {
            mClusterImageView.setBackgroundResource(R.drawable.temp_20_a_24);
        } else if ((tempAvg/cluster.getSize()) <= 19 && (tempAvg/cluster.getSize()) >= 15) {
            mClusterImageView.setBackgroundResource(R.drawable.temp_15_a_19);
        } else if ((tempAvg/cluster.getSize()) <= 14 && (tempAvg/cluster.getSize()) >= 10) {
            mClusterImageView.setBackgroundResource(R.drawable.temp_10_a_14);
        } else if ((tempAvg/cluster.getSize()) <= 9 && (tempAvg/cluster.getSize()) >= 5) {
            mClusterImageView.setBackgroundResource(R.drawable.temp_5_a_9);
        } else if ((tempAvg/cluster.getSize()) <= 4) {
            mClusterImageView.setBackgroundResource(R.drawable.temp_4_o_menos);
        }

        for (ItemCluster item : cluster.getItems()) {
            vientoStr = item.getViento();
            if (Objects.equals(vientoStr, "appvalenciaplayas/static/images/viento/viento_NE2.svg")) {
                mClusterViento.setImageResource(R.drawable.viento_ne2);
            } else if (Objects.equals(vientoStr, "appvalenciaplayas/static/images/viento/viento_NW2.svg")) {
                mClusterViento.setImageResource(R.drawable.viento_nw2);
            } else if (Objects.equals(vientoStr, "appvalenciaplayas/static/images/viento/viento_E2.svg")) {
                mClusterViento.setImageResource(R.drawable.viento_e2);
            } else if (Objects.equals(vientoStr, "appvalenciaplayas/static/images/viento/viento_NE1.svg")) {
                mClusterViento.setImageResource(R.drawable.viento_ne1);
            } else if (Objects.equals(vientoStr, "appvalenciaplayas/static/images/viento/viento_NE3.svg")) {
                mClusterViento.setImageResource(R.drawable.viento_ne3);
            } else if (Objects.equals(vientoStr, "appvalenciaplayas/static/images/viento/viento_NE4.svg")) {
                mClusterViento.setImageResource(R.drawable.viento_ne4);
            } else if (Objects.equals(vientoStr, "appvalenciaplayas/static/images/viento/viento_NW1.svg")) {
                mClusterViento.setImageResource(R.drawable.viento_nw1);
            } else if (Objects.equals(vientoStr, "appvalenciaplayas/static/images/viento/viento_NW3.svg")) {
                mClusterViento.setImageResource(R.drawable.viento_nw3);
            } else if (Objects.equals(vientoStr, "appvalenciaplayas/static/images/viento/viento_NW4.svg")) {
                mClusterViento.setImageResource(R.drawable.viento_nw4);
            } else if (Objects.equals(vientoStr, "appvalenciaplayas/static/images/viento/viento_E1.svg")) {
                mClusterViento.setImageResource(R.drawable.viento_e1);
            } else if (Objects.equals(vientoStr, "appvalenciaplayas/static/images/viento/viento_E3.svg")) {
                mClusterViento.setImageResource(R.drawable.viento_e3);
            } else if (Objects.equals(vientoStr, "appvalenciaplayas/static/images/viento/viento_E4.svg")) {
                mClusterViento.setImageResource(R.drawable.viento_e4);
            } else if (Objects.equals(vientoStr, "appvalenciaplayas/static/images/viento/viento_N1.svg")) {
                mClusterViento.setImageResource(R.drawable.viento_n1);
            } else if (Objects.equals(vientoStr, "appvalenciaplayas/static/images/viento/viento_N2.svg")) {
                mClusterViento.setImageResource(R.drawable.viento_n2);
            } else if (Objects.equals(vientoStr, "appvalenciaplayas/static/images/viento/viento_N3.svg")) {
                mClusterViento.setImageResource(R.drawable.viento_n3);
            } else if (Objects.equals(vientoStr, "appvalenciaplayas/static/images/viento/viento_N4.svg")) {
                mClusterViento.setImageResource(R.drawable.viento_n4);
            } else if (Objects.equals(vientoStr, "appvalenciaplayas/static/images/viento/viento_W1.svg")) {
                mClusterViento.setImageResource(R.drawable.viento_w1);
            } else if (Objects.equals(vientoStr, "appvalenciaplayas/static/images/viento/viento_W2.svg")) {
                mClusterViento.setImageResource(R.drawable.viento_w2);
            } else if (Objects.equals(vientoStr, "appvalenciaplayas/static/images/viento/viento_W3.svg")) {
                mClusterViento.setImageResource(R.drawable.viento_w3);
            } else if (Objects.equals(vientoStr, "appvalenciaplayas/static/images/viento/viento_W4.svg")) {
                mClusterViento.setImageResource(R.drawable.viento_w4);
            } else if (Objects.equals(vientoStr, "appvalenciaplayas/static/images/viento/viento_SW1.svg")) {
                mClusterViento.setImageResource(R.drawable.viento_sw1);
            } else if (Objects.equals(vientoStr, "appvalenciaplayas/static/images/viento/viento_SW2.svg")) {
                mClusterViento.setImageResource(R.drawable.viento_sw2);
            } else if (Objects.equals(vientoStr, "appvalenciaplayas/static/images/viento/viento_SW3.svg")) {
                mClusterViento.setImageResource(R.drawable.viento_sw3);
            } else if (Objects.equals(vientoStr, "appvalenciaplayas/static/images/viento/viento_SW4.svg")) {
                mClusterViento.setImageResource(R.drawable.viento_sw4);
            } else if (Objects.equals(vientoStr, "appvalenciaplayas/static/images/viento/viento_SE1.svg")) {
                mClusterViento.setImageResource(R.drawable.viento_se1);
            } else if (Objects.equals(vientoStr, "appvalenciaplayas/static/images/viento/viento_SE2.svg")) {
                mClusterViento.setImageResource(R.drawable.viento_se2);
            } else if (Objects.equals(vientoStr, "appvalenciaplayas/static/images/viento/viento_SE3.svg")) {
                mClusterViento.setImageResource(R.drawable.viento_se3);
            } else if (Objects.equals(vientoStr, "appvalenciaplayas/static/images/viento/viento_SE4.svg")) {
                mClusterViento.setImageResource(R.drawable.viento_se4);
            } else if (Objects.equals(vientoStr, "appvalenciaplayas/static/images/viento/viento_S1.svg")) {
                mClusterViento.setImageResource(R.drawable.viento_s1);
            } else if (Objects.equals(vientoStr, "appvalenciaplayas/static/images/viento/viento_S2.svg")) {
                mClusterViento.setImageResource(R.drawable.viento_s2);
            } else if (Objects.equals(vientoStr, "appvalenciaplayas/static/images/viento/viento_S3.svg")) {
                mClusterViento.setImageResource(R.drawable.viento_s3);
            } else if (Objects.equals(vientoStr, "appvalenciaplayas/static/images/viento/viento_S4.svg")) {
                mClusterViento.setImageResource(R.drawable.viento_s4);
            }
            break;
        }


        mClusterIconGenerator.setBackground(TRANSPARENT_DRAWABLE);
        Bitmap bitmap = mClusterIconGenerator.makeIcon(String.valueOf(cluster.getSize()));
        markerOptions.icon(BitmapDescriptorFactory.fromBitmap(bitmap));
    }


    @Override
    protected boolean shouldRenderAsCluster(Cluster cluster) {
        // Always render clusters.
        return cluster.getSize() > 1;
    }
}


@Override
public void onResume() {
    super.onResume();
    mapView.onResume();
}

@Override
public void onDestroy() {
    super.onDestroy();
    mapView.onDestroy();
}

@Override
public void onPause() {
    super.onPause();
    mapView.onPause();
}

@Override
public void onLowMemory() {
    super.onLowMemory();
    mapView.onLowMemory();
}

@Override
public void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    mapView.onSaveInstanceState(outState);
     }
 }
@mohamedagamy
Copy link

there is no answers or updates or any workaround to this issue ?

@AryaRDI
Copy link
Author

AryaRDI commented Jan 17, 2018

it is old, I guess the only way is that you save the state of the map before any change then reload it again from the stack

cheers

@mohamedagamy
Copy link

thanks 💯

@basitsaleemmb
Copy link

didn't get your ans. please elaborate little bit more @AryaRDI .
thanks !

@stale
Copy link

stale bot commented Oct 3, 2019

This issue has been automatically marked as stale because it has not had recent activity. Please comment here if it is still valid so that we can reprioritize. Thank you!

@stale stale bot added the stale label Oct 3, 2019
@alneil
Copy link

alneil commented Oct 30, 2019

i have same trouble

@stale stale bot removed the stale label Oct 30, 2019
@wangela
Copy link
Contributor

wangela commented Dec 30, 2019

In the future, for help with specific situations you'll get the fastest response on StackOverflow (tag google-maps-android-api-2).

For this question, you may want to check out the demos for RetainMap and SaveState.

@wangela wangela closed this as completed Dec 30, 2019
@tutucmarin
Copy link

You could try to "Add" fragments instead of replacing them.
It will not destroy the previous fragment view, so it won't be necessary to reload the data.

Example:

        val fragment = TheFragment()
        val ft = requireActivity().supportFragmentManager.beginTransaction()

        ft.add(R.id.fragment_container, fragment)
        ft.commit()

@Photon-thing
Copy link

Photon-thing commented Feb 28, 2022

Well it's maybe too late and the problem is solved, but for others with that problem the solution from me can help.

I had the same problem with a laggy map when switching between fragments from navigation in one activity. I think it's a specific way to implement such a structure but anyway.

So the solution for the map to just save the map in its rendered status and don't mess up recreating it when getting back to the fragment, is to check if its not null.

so I use the MapFragment, but you could change your code to fit into it.

In your MainFragment.java you have to check it your actual Map is not null

In the onCreateView Method from Fragment:

if (mMap == null) {
fusedLocationProviderClient = getFusedLocationProviderClient(getActivity());
SupportMapFragment supportMapFragment = (SupportMapFragment) getChildFragmentManager().findFragmentById(R.id.mapView);
supportMapFragment.getMapAsync(this);
}

So the getMapAsync Task is only called when there is no initialized Map and while there was one he is using it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants