0

I'm having a lot of trouble with Android Fragments, and I don't know why.

I want to keep an object in memory whenever I pause the app (onPause()).

I have a MapView with some layers. And I want to keep those layers, so the map doesn't have to reload from scratch and recreate them whenever I pause and resume the app.

The thing is, I can't save them with onSaveInstanceState(). They are objects, not primitives. They are also from a library, so I can't make them implement Serializable or Parcelable.

I want to find a solution without resorting to:

android:configChanges="orientation|screenSize">

to my Activity, since it is considered bad practice. Also, it doesn't work for when you pause and resume the app.

I also tried

this.setRetainInstance(true); // retain this fragment

on my fragment's onCreate(), but I would also like to avoid it. It doesn't work anyway.

After much trial, error and testing, I found out that my fragment's onSaveInstanceState() doesn't even run. I can't even keep a simple boolean whenever I pause and resume the app.

I read:

Saving Android Activity state using Save Instance State

https://developer.android.com/training/basics/activity-lifecycle/recreating

savedInstanceState is always null

Amog many other posts and, of course, the Android documentation.

Some of my code:

Creating the fragment:

    navFragment = FragNavigation.newInstance(); // keeping the reference to the navFragment

    // setting up the viewpager
    ViewPager viewPager = findViewById(R.id.vpMainViewPager);
    MainPagerAdapter mainAdapter = new MainPagerAdapter(getSupportFragmentManager(), this);
    mainAdapter.addFragment(navFragment);
    viewPager.setAdapter(mainAdapter);

Trying to save a simple boolean in the instance state (remember: this doesn't even run):

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

    Log.e(TAG, "onSaveInstanceState: is map loaded? " + mapIsLoaded );

    outState.putBoolean("mapIsLoaded", mapIsLoaded);
}

And trying to load it:

@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    this.setRetainInstance(true); // retain this fragment

    Log.e(TAG, "onCreate: null? " + (savedInstanceState == null) );

    if (savedInstanceState != null)
        mapIsLoaded = savedInstanceState.getBoolean("mapIsLoaded", false);
}

What am I missing? I'm clearly not understanding something. Why is it so hard to keep values when you pause the app?

Luís Henriques
  • 546
  • 6
  • 20

2 Answers2

1

I would suggest storing the MapView layers using a ViewModel as per Architecture Components. If that is not an option, you can manually store and retrieve objects using the Activities getLastNonConfigurationInstance.

Freddroid
  • 2,429
  • 19
  • 23
  • Cool. Never knew about ViewModel. Gonna look into that and come back to your answer. Thanks. – Luís Henriques Sep 19 '18 at 17:31
  • Well, it worked for the rotation. Not for pausing and unpausing the activity. Why is this so hard? Isn't this a standard operation? – Luís Henriques Sep 19 '18 at 19:59
  • Pausing/Resuming an Activity wouldn't cause them to become GC'd unless you have calls in the start of the lifecycle that inadvertently overwrites them? – Freddroid Sep 21 '18 at 11:14
  • No. I have no such thing. I'll make a test application tomorrow to really figure this out. As I said, I'm probably missing somehing very obvious. I need to read some more. – Luís Henriques Sep 23 '18 at 20:46
  • 1
    I ended up using a static private object that extends ViewModel and encapsulates all map elements. In the fragment's onCreate(), I instantiate the ViewModel if it is null, and, if it's not, I read all map elements from it. Thanks for the tip. – Luís Henriques Sep 25 '18 at 18:33
0
 @Override
    public void onPause() {
        /**
         * store your data 

         */

        super.onPause();
    }

    @Override
    public void onResume() {
        /**
         * retrieve your data       
         */



        super.onResume();
    }
  • Thanks. You mean store my data on sharedPreferences? Because you can only save primitives and serializables in sharedPrefs. And it's not ideal. I mean, all I want is to prevent map reloading. – Luís Henriques Sep 19 '18 at 17:30