0

I was able to save outState as follows but was unable to restore when I land on this AttendanceFragment.cs second time.

 public override void OnSaveInstanceState(Bundle outState)
    {
        base.OnSaveInstanceState(outState);
        dataGotFromServer = JsonConvert.SerializeObject(dataList);
        outState.PutString(KEY_OUTSTATE, dataGotFromServer);
    }

I tried here to restore but could not get it

 public override void OnViewStateRestored(Bundle savedInstanceState)
    {
        base.OnViewStateRestored(savedInstanceState);
        if(savedInstanceState!=null)
        {
            var result = savedInstanceState.GetString(KEY_OUTSTATE, dataGotFromServer);
        }

    }

and also I tried on CreateView(), OnActivityCreated() and On Create() but unsuccessfull to restore.

And my code for fragment replacement is as

 public void ReplaceFragment(Context context, Fragment newFragment, string TAG)
    {
        Android.Support.V4.App.FragmentManager fragmentManager = ((FragmentActivity)context).SupportFragmentManager;
        Android.Support.V4.App.FragmentTransaction ft = fragmentManager.BeginTransaction();
        ft.Replace(Resource.Id.HomeFrameLayout, newFragment);
        ft.AddToBackStack(TAG);
        ft.Commit();

    }

Edited: This is how I call this fragment

 case (Resource.Id.nav_attendance):


                var role = session.GetUserDetails().Get(SessionManagement.KEY_ROLE).ToString();
                if (role=="Student")
                {
                    Fragment attendanceTabFragment = new AttendanceTabFragment();
                    customFragment.ReplaceFragment(this, attendanceTabFragment,typeof(AttendanceTabFragment).Name);
                }else
                {
                    Fragment attendanceFragment = new AttendanceFragment();
                    customFragment.ReplaceFragment(this, attendanceFragment, typeof(AttendanceFragment).Name);
                }

Any idea or sample code much appreciated. Thank you.

Ishwor Khanal
  • 1,312
  • 18
  • 30
  • Please look [https://stackoverflow.com/questions/40949274/saving-and-restoring-state-using-fragments] this link. – Alok Mishra Aug 17 '17 at 05:08
  • Can you add how you calling `ReplaceFragment`? – SushiHangover Aug 17 '17 at 05:12
  • When do you expect it to restore? Please describe what user does, what you expect to happen, and what happens? – lionscribe Aug 17 '17 at 05:17
  • I have menu option named Attendance on Navigation Drawer and its click event maintained in activity then user lands on this fragment. So, first time its fine to call webserver to pull data afterwards if user clicks on this option, I would like to restore data rather than calling again webserver. – Ishwor Khanal Aug 17 '17 at 08:13
  • @SushiHangover I have edited code for your reference. – Ishwor Khanal Aug 17 '17 at 08:18
  • You are not restoring Fragments, you keep in creating new ones and piling them on onto the backStack. You should be using FindFragmentByTag. I see that @SushiHangover has given you an example. – lionscribe Aug 17 '17 at 11:51

1 Answers1

1

Unless the Activity that contains the Fragment get disposed, Fragment's OnSaveInstanceState is not going to be called.

In a situation were you are swapping Fragments in and out, using Fragment.Arguments is an option instead of a singleton/static var...

re: getArguments / setArguments

In using arguments:

  1. Create a new Bundle in the Fragment constructor and assign it to Arguments
  2. In the OnPause override update the Arguments/Bundle with the items you need to save.
  3. In the OnResume override read the Arguments/Bundle items that you need to restore.

Example Fragment:

public class Fragment1 : Fragment
{
    public Fragment1(System.IntPtr javaReference, Android.Runtime.JniHandleOwnership transfer) : base(javaReference, transfer)
    {
        CreateArgumentBundle();
    }

    public Fragment1()
    {
        CreateArgumentBundle();
    }

    void CreateArgumentBundle()
    {
        Arguments = new Bundle();
    }

    public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
    {
        return inflater.Inflate(Resource.Layout.Frag1, container, false);
    }

    public override void OnPause()
    {
        base.OnPause();
        Arguments.PutString("someKey", "StackOverflow");
    }

    public override void OnResume()
    {
        base.OnResume();
        var someKeyString = Arguments.GetString("someKey", "someDefaultString(new bundle)");
        Log.Debug("SO", someKeyString);
    }
}

In your ReplaceFragment make sure that you are assigning the TAG in the Replace call:

public void ReplaceFragment(Context context, Fragment newFragment, string TAG)
{
    SupportFragmentManager
        .BeginTransaction()
        .Replace(Resource.Id.fragmentContainer, newFragment, TAG)
        .AddToBackStack(TAG)
        .Commit();
}

Before calling your ReplaceFragment, check to see if the Fragment exists (FindFragmentByTag) before creating a new one, this example just swaps two fragments in and out and only creates new ones if the manager does not contain one:

button.Click += delegate
{
    toggle = !toggle;
    var frag = SupportFragmentManager.FindFragmentByTag(toggle ? "frag1" : "frag2");
    frag = frag ?? ( toggle ? (Fragment)new Fragment1() : (Fragment)new Fragment2() );
    ReplaceFragment(this, frag, toggle ? "frag1" : "frag2");
};

Note: You will still need to handle the other Fragment lifecycle events in the case that the hosting Activity is recycled:

SushiHangover
  • 73,120
  • 10
  • 106
  • 165