4

I am using a navigation bar in my app and each time I choose an item it loads a fragment.

I was able to save the state of a fragment with same text fields and buttons but there is a fragment that loads a map, add markers, clusters and executes an AsyncTask.

Each time I go to another menu item and come back it reloads everything again like AsyncTask, Cluster, Markers. How can i stop this fragment to not recreate the map again and save the state when it comes back:

Udate 1: i Update the code but the problem still remained

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 = "SOME_JSON_URL";


        @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);
    }
}
Blacksword
  • 331
  • 3
  • 17
  • Instead of replacing the map fragment, you could add the fragment on top. The map would still be there but be hidden behind the new fragment. – apmartin1991 Sep 07 '16 at 11:04
  • when i use add instead of replace my app crashes after i open a fragment once and come back again to that fragment – Blacksword Sep 07 '16 at 11:16
  • What is the crash log for that? Please ammend question with that too. – apmartin1991 Sep 07 '16 at 11:37
  • com.compscitutorials.basigarcia.navigationdrawervideotutorial E/AndroidRuntime: FATAL EXCEPTION: main Process: com.compscitutorials.basigarcia.navigationdrawervideotutorial, java.lang.IllegalStateException: Fragment already added: MainFragment{78750c1 #2 id=0x7f0e008c} android.support.v4.app.FragmentManagerImpl.addFragment(FragmentManager.java:1361) android.support.v4.app.BackStackRecord.run(BackStackRecord.java:734) android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1677) android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:536) – Blacksword Sep 07 '16 at 12:02
  • instead of calling the fragment code (addFragment) you want to call popBackStack(); – apmartin1991 Sep 07 '16 at 14:46
  • 1
    @apmartin1991can you make it clear in an answer please? – Blacksword Sep 07 '16 at 18:03
  • Did you solve this issue? – Mahdi Nov 29 '19 at 07:28

2 Answers2

0

You are replacing the fragment after every event, please add the fragment to the backstack and then pop it from the backstack. Then it will work. Check the below code:

FragmentManager fragmentManager = getFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.add(android.R.id.content, testFragment);
fragmentTransaction.addToBackStack(TAG);
fragmentTranscation.commit();
Dhaval Shah
  • 618
  • 6
  • 15
Manoj Perumarath
  • 9,337
  • 8
  • 56
  • 77
  • it doesn't seems right because when you use beginTransaction(); you should commit() it no? and where should i pop it up? – Blacksword Sep 07 '16 at 11:28
  • Then check the FragmentManager fragmentManager = getFragmentManager(); fragmentManager.getBackStackEntryCount() and pop the stack. – Manoj Perumarath Sep 07 '16 at 11:35
  • 1
    please update the code and show how to pop it up from the stack as you can see in my code i'm not using fragmentmanager to handle this – Blacksword Sep 07 '16 at 12:17
0

Google Maps' Docs say:

Users of this class must forward all the life cycle methods from the Activity or Fragment containing this view to the corresponding ones in this class. In particular, you must forward on the following methods:

  • onCreate(Bundle)
  • onResume()
  • onPause()
  • onDestroy()
  • onSaveInstanceState()
  • onLowMemory()

So in your MainFragment.java, you'd MUST override all of the methods above and delegate the calls to mapView.

For clarity, you'd override onSaveInstanceState() like this:

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

Edit

Other problem is that you're creating MainFragment first time without caching it. Which means that you do not "re-use" this instance when you bring back the one from drawer (you can check by clicking drawer items in this order nav_gallery -> nav_camera -> nav_gallery -> nav_camera. The MainFragment at 4th position should not load like the one at 2nd):

Fragment fragment = new MainFragment(jArray);
myFragments.put(1, fragment);

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

Edit2

For maintaining the state of your Fragment, you will have to do following things:

  1. update your onSaveInstanceState(), to save its state, like following:

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        mapView.onSaveInstanceState(outState);
        outState.putString("jsonArr", jsonArray.toString());
        // TODO put more things which you need to.
    }
    
  2. update your onCreateView(), to restore the state, like:

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        if (savedInstanceState != null) {
            String jsonArrString = savedInstanceState.getString("jsonArr");
            try {
                jsonArray = new JSONArray(jsonArrString);
            }
            catch (Exception e) {
                e.printStackTrace()
            }
        }
        // TODO your old code goes after this line.
    }
    
Sufian
  • 6,405
  • 16
  • 66
  • 120
  • yes of course i did it but as we discussed in other topic it doesnt work on map with that method you gave me – Blacksword Sep 08 '16 at 07:53
  • @AryaR. are you overriding all the methods listed? Can you update your question with the latest code of `MainFragment`? – Sufian Sep 08 '16 at 08:18
  • yes, unless onCeate because i used it in my onCreateView as " mapView.onCreate(savedInstanceState);" – Blacksword Sep 08 '16 at 09:11
  • @AryaR. this could cause trouble. Call `mapView.onCreate()` from `onCreate()` of your Fragment. And please update the code. Can't suggest much without looking at the code. – Sufian Sep 08 '16 at 10:25
  • i uptaded the code, when i create the Override method onCreate and put the: mapView.onCreate() there the app crash – Blacksword Sep 08 '16 at 10:46
  • **1.** move ` mapView.onCreate(savedInstanceState);` to Fragment's `onCreate()`, **2.** if crash still occurs, post your LogCat + steps to reproduce it. – Sufian Sep 08 '16 at 10:50
  • this is the error: `2488-2488/com.compscitutorials.basigarcia.navigationdrawervideotutorial E/AndroidRuntime: FATAL EXCEPTION: main Process: com.compscitutorials.basigarcia.navigationdrawervideotutorial, PID: 2488java.lang.RuntimeException: Unable to start activity ComponentInfo{com.compscitutorials.basigarcia.navigationdrawervideotutorial/com.compscitutorials.basigarcia.navigationdrawervideotutorial.MainActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'void com.google.android.gms.maps.MapView.onCreate(android.os.Bundle)' on a null object referenceat ` – Blacksword Sep 08 '16 at 11:16
  • @AryaR. it's a NullPointerException. You will have to move `mapView.onCreate(savedInstanceState);` to your `onCreateView()` and after you've done `mapView = (MapView) rootView.findViewById(R.id.map);`. I completely forgot that `onCreateView()` is called after `onCreate()`. – Sufian Sep 08 '16 at 11:50
  • so? if you take a look to the code it is exactly like this – Blacksword Sep 08 '16 at 11:55
  • @AryaR. well, it is because the field `mapView` is null. You have to debug to know why is it so. Maybe it is not there in your layout? Or not assigned that id? Or maybe you need to clean build (and disable "instant run"). – Sufian Sep 08 '16 at 12:23
  • it is not null the app is working if it was null `if (mapView != null)` this couldn't be excuted that was null because as you told me i put the mapview inside Override method on onCreate – Blacksword Sep 08 '16 at 12:31
  • It should be null because LogCat can't be null. "as you told me i put the mapview inside Override method on onCreate" Not put it in `onCreateView()` like you have in your code question. If it doesn't work, post your layout XML. – Sufian Sep 08 '16 at 13:13
  • no it works but the problem is still remain when i choose a fragment and come back it recreates itself – Blacksword Sep 08 '16 at 13:20
  • @AryaR. it might be because you're doing `new MainFragment()` at two places. It should always pick from `myFragments` (and doing that if-statement). And what is your flow? Does it happen even after you've selected "nav_camera" from menu? – Sufian Sep 08 '16 at 13:36
  • i don't think so because the activity runs once then you only can navigate between menu items you cant restart the activity if you close the program yes btw i tried by removing the part in oncreat in main activity so it brought an empty fragment then i navigate between menu but the problem still remains – Blacksword Sep 08 '16 at 13:52
  • @AryaR. you didn't mention your flow. How do you navigation, press back, select from drawer? Could you state it briefly? It will clear things a bit. – Sufian Sep 08 '16 at 14:10
  • i mentioned select from drawer – Blacksword Sep 08 '16 at 22:15
  • @AryaR. not clear enough. Confirm if this is what you do: launch the app (MainFragment is showing), select "nav_gallery" from drawer, then select "nav_camara" from drawer (to bring back mapView). If this is how you're doing it, see my updated answer. – Sufian Sep 09 '16 at 01:11
  • @AryaR. I guess you will need to save the state manually. See [this answer](http://stackoverflow.com/a/16348984/1276636). – Sufian Sep 09 '16 at 07:25
  • the solution for that answer is the user chose/add some markers on map or zoom then the user change fragment and comeback so the changed he did will come back, but in my app the user only see the markers and clusters which load from my json this loading of clusters and markers take 1-2 second because of calculation i don't wanna save the cluster and marker possition because they are tehre in my json i wanna save the whole fragment to prevent a reload, fine? – Blacksword Sep 09 '16 at 08:23
  • @AryaR. unfortunately Android doesn't work this way. You can not stop Fragment or Activity from being destroyed or in case of Fragment it can also mean that only the View is destroyed (which the OS decides when to do it, and you can't influence it). What will make sense is that you store your objects in the `Bundle` in your Fragment's `onSaveInstanceState()` and restore it in `onActivityCreated()`. – Sufian Sep 09 '16 at 09:26
  • how i should make it done? can you give me an example? – Blacksword Sep 09 '16 at 10:50
  • it pass the array of json not the markers and clusters, i have an idea how if we hide show the fragment when we navigate in menu? – Blacksword Sep 09 '16 at 12:56
  • @AryaR. fooling the Android OS will make things difficult for you in development, and will break the app unexpectedly. What do you mean by "it pass the array of json not the markers and clusters"? – Sufian Sep 09 '16 at 13:12
  • here: outState.putString("jsonArr", jsonArray.toString()); we are saving the parsed json file as a string and saving it till we call again the fragment right? – Blacksword Sep 09 '16 at 13:15
  • @AryaR. yes. And you can follow that with whatever you think needs to be saved. If you need to save marker, refer to [this answer](http://stackoverflow.com/a/16348984/1276636). In addition to the answer, you'll save it in `onSaveInstanceState()`. Let me know if it helps. – Sufian Sep 09 '16 at 13:22
  • this weekend i tried many methods and tricks it hasn't worked for me, as i diagnosed the app the problem is everytime we call the fragment it makes a new onCreateView from beginning and when it starts, it will run my for loop inside MainFragment and it makes the app to freez and recreate the clusters and markers, so tehre is 2 way first somehow to put the fragment on Pause in background then bring it front or pass the clusters with onSaveInstanceState() is it be possible to save the state of arraylist mClusterManager ? – Blacksword Sep 12 '16 at 12:31
  • @AryaR. The first time you will have `savedInstanceState` null but it should be non-null the next time. You have to live with that. Typical annoying Android OS thingy. You will speed it up a bit by not fetching the JSON again but I guess you can't really avoid view creation. – Sufian Sep 12 '16 at 19:02
  • yea but as i checked in documents of google it said you can only save some specific data types and this is the problem – Blacksword Sep 13 '16 at 06:11
  • @AryaR. you can also store custom objects (also known as POJO) if they implement `Serializable` or `Parcelable` interfaces. See [this answer about making a POJO a parcelable](http://stackoverflow.com/questions/7181526/how-can-i-make-my-custom-objects-be-parcelable) or [Serialazible which is easier](http://stackoverflow.com/questions/14333449/passing-data-through-intent-using-serializable). You can use the `serializable` one because it will be easier for you. – Sufian Sep 13 '16 at 07:46