Search code examples
javaandroidandroid-savedstate

How save the state of the item on my fragment?


I'm getting a ArrayList from an Url with AsyncTask, and inserting into an ListView on my Fragmentbut everytime I change fragments I have to get json data from the Url again so I tried to use onSaveInstanceState() to save my ArrayList as a String and transform to my ArrayList using JsonObject and Gson Library but I can't save the data.

OnSave method

      @Override
            public void onSaveInstanceState(@NonNull Bundle outState) {
            outState.putString("cursos", this.cursosString);

            super.onSaveInstanceState(outState);
      }

OnCreateView method

    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    View view = inflater.inflate(R.layout.fragment_cursos, container, false);
    final ListView lvCursos = view.findViewById(R.id.lvCursos);

    if(savedInstanceState != null){

        Type arrayListCurso = new TypeToken<ArrayList<Curso>>(){}.getType();
        ArrayList<Curso> cursos = new Gson().fromJson(savedInstanceState.getString("cursos"), arrayListCurso);
        ListaCursosAdapter adapter = new ListaCursosAdapter(cursos, getActivity());
        lvCursos.setAdapter(adapter);

    } else {
    ...

Change Fragments method

   public boolean onNavigationItemSelected(@NonNull MenuItem menuItem) {

    switch (menuItem.getItemId()){

        case R.id.navigation_profile:
            getSupportFragmentManager()
                    .beginTransaction()
                    .replace(R.id.nav_fragment, perfilFragment)
                    .commit();
            return true;

Solution

  • Here is the solution, you just left to decide how to implement getTagForFragmentId() and getFragmentForFragmentTag(fragmentTag), which should be simple.

    The idea of the code below is that you .hide() previous fragment presented and then you either .add(fragment) a new fragment, if it was not previously presented or .show() fragment if it is already inside the backstack.

    String lastPresentedFragmentTag = "";
    
    public boolean onNavigationItemSelected(@NonNull MenuItem menuItem) {
        switch (menuItem.getItemId()){
            case R.id.navigation_profile:
                // getTagForFragmentId() can be just a switch case function
                // or you can hardcode value instead
                String fragmentTag = getTagForFragmentId(R.id.navigation_profile);
                presentFragment(fragmentTag);
                return true;
            //...
    
    
    public void presentFragment(String fragmentTag) {
        if (lastPresentedFragmentTag == fragmentTag) {
            return;
        }
    
        FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
        // Hide previous fragment
        if (lastPresentedFragmentTag != null) {
            Fragment lastFragmenter code hereent = getSupportFragmentManager().findFragmentByTag(lastPresentedFragmentTag);
            ft.hide(lastFragment);
        }
    
        Fragment currentFragment = getSupportFragmentManager().findFragmentByTag(fragmentTag);
        if (currentFragment == null) {
    
                // Implement getFragmentForFragmentTag(fragmentTag) it will be another switch case function that will return you fragment
                val fragment = getFragmentForFragmentTag(fragmentTag);
                transaction.add(R.id.fragmentContainer, fragment, tag);
            } else {
                transaction.show(currentFragment);
            }
        }
    
        transaction.commitNow();
    }