0

I have SettingActivity. It contains SettingFragment (with ListPreference) and another AudioSamplingSeekBarFragment(with my custom preference in it). When i choose some item in ListPreference, i recreate my AudioSamplingSeekBarFragment with chosen data from ListPreference. like this:

public class SettingsFragment extends PreferenceFragment {
private static Logger log = Logger.getLogger(SettingsFragment.class.getName());
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    addPreferencesFromResource(R.xml.preferences);

    ListPreference outputFormatPref = (ListPreference) findPreference(getResources().getString(R.string.key_encoder));
    outputFormatPref.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
        @Override
        public boolean onPreferenceChange(Preference preference, Object newValue) {
            MySharedPreferences.setAudioEncoder(getActivity(), (String) newValue);
            **embedSeekBarWithFormat((String) newValue);**
            return true;
        }
    });
}

**public void embedSeekBarWithFormat(String format) {
    try {
        FragmentManager manager = getFragmentManager();
        FragmentTransaction transaction = manager.beginTransaction();
        AudioSamplingSeekBarFragment fragment = (AudioSamplingSeekBarFragment) manager.findFragmentByTag(AudioSamplingSeekBarFragment.TAG);
        if (manager.findFragmentByTag(AudioSamplingSeekBarFragment.TAG) != null) {
            transaction.remove(fragment);
        }
        AudioSamplingSeekBarFragment newFragment = new AudioSamplingSeekBarFragment();
        Bundle bundle = new Bundle();
        bundle.putInt(AudioSamplingSeekBarFragment.STATE_FORMAT, Integer.parseInt(format));
        newFragment.setArguments(bundle);  
        transaction.add(R.id.seekBar_container, newFragment, AudioSamplingSeekBarFragment.TAG);
        transaction.commit();
    } catch (Exception e) {
        log.log(Level.SEVERE, "Exception: ", e);
    }
}
}**

So when i quite the SettingActivity and go into again my AudioSamplingSeekBarFragment doesn't save state.

I put my fragment in onSaveInstanceState() in SettingsActivity as they say here: topic

public class SettingsActivity extends android.support.v7.app.ActionBarActivity {
  @Override
  protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_preferences);
    if (savedInstanceState != null) {
        getFragmentManager()
                .beginTransaction()
                .add(R.id.seekBar_container, getFragmentManager().getFragment(savedInstanceState, AudioSamplingSeekBarFragment.TAG) , AudioSamplingSeekBarFragment.TAG)
                .commit();
    } else {
        getFragmentManager()
                .beginTransaction()
                .add(R.id.seekBar_container, new AudioSamplingSeekBarFragment(), AudioSamplingSeekBarFragment.TAG)
                .commit();
    }
  }
@Override
protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
        getFragmentManager()
                .putFragment(outState, AudioSamplingSeekBarFragment.TAG, getFragmentManager().findFragmentByTag(AudioSamplingSeekBarFragment.TAG));
}

And save specific data in onSaveInstanceState() in Fragment:

public class AudioSamplingSeekBarFragment extends Fragment {
public static final String TAG = "SEEK_BAR_FRAGMENT_TAG";
public static final String STATE_FORMAT = "format";
private int format;
private int seekBarInitVal;

**@Override
public void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    outState.putInt(STATE_FORMAT, format);
}**

@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {
    return inflater.inflate(R.layout.fragment_audio_sampling_seekbar, container,false);
}

And i'm expecting to restore saved data here:

@Override
public void onViewCreated(final View view, @Nullable Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    if (savedInstanceState != null) {
        **format = savedInstanceState.getInt(STATE_FORMAT);**
    } else  if (getArguments() != null){
        format = getArguments().getInt(STATE_FORMAT);
    } else {
        format = AAC;
    }
    SeekBar seekBar = (SeekBar)view.findViewById(R.id.sample_rate_seek_bar);
    final TextView textProgress = (TextView) view.findViewById(R.id.progress);
    switch (format) {
        case AAC:
            seekBarInitVal = 8000;
            seekBar.setMax(40000);
            break;
        case AAC_ELD:
            seekBarInitVal = 16000;
            seekBar.setMax(32000);
            break;
        case AMR_NB:
            seekBarInitVal = 8000;
            seekBar.setEnabled(false);
            break;
        case AMR_WB:
            seekBarInitVal = 16000;
            seekBar.setEnabled(false);
            break;
        case HE_AAC:
            seekBarInitVal = 8000;
            seekBar.setMax(40000);
            break;
    }
    textProgress.setText("" + seekBarInitVal + " Hz");


    seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
        @Override
        public void onProgressChanged(SeekBar seekBar, int i, boolean b) {
            i += seekBarInitVal;
            textProgress.setText("" + i + " Hz");
        }

        @Override
        public void onStartTrackingTouch(SeekBar seekBar) {

        }

        @Override
        public void onStopTrackingTouch(SeekBar seekBar) {

        }
    });
}
}

But it doesn't work.

Just in case layouts:

activity_preference:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">
    <include
        android:id="@+id/toolbar"
        layout="@layout/toolbar"/>
    <FrameLayout
        android:id="@+id/preferences_container"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
    <FrameLayout
        android:id="@+id/seekBar_container"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"/>
</LinearLayout>
fragment_audio_sampling_seekbar:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/seekBar_fragment">
    <View
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:background="#dbdbdd" />

    <TextView
        android:id="@+id/summary"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentStart="true"
        android:layout_alignParentTop="true"
        android:layout_marginStart="15dp"
        android:layout_marginTop="14dp"
        android:text="Set Audio Sampling Rate"
        android:textAppearance="@style/TextAppearance.AppCompat" />

    <SeekBar
        android:id="@+id/sample_rate_seek_bar"
        android:layout_width="303dp"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_alignStart="@+id/summary"
        android:layout_marginTop="40dp" />

    <TextView
        android:id="@+id/progress"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_alignStart="@+id/summary"
        android:layout_marginTop="66dp"/>

    <View
        android:layout_width="match_parent"
        android:layout_height="1dp"
        android:layout_alignParentStart="true"
        android:layout_alignParentTop="true"
        android:layout_marginTop="96dp"
        android:background="#dbdbdd" />

</RelativeLayout>
  • So, i find out, that we can't build logics with onSaveInstantSave, because it invokes only when SYSTEM decides to delete the activity, but not when we click back button. So i just save required parametrs into SharedPreferences and implements with them in onCreate() if they exists. – Сяргей Скуратовіч Dec 17 '18 at 16:23

1 Answers1

0

As far as I was aware, SavedInstanceState only stores a Bundle of data. Only basic things such as Strings, Integers etc. and does not hold anything like Views.

I think you should really use a ViewModel as it can hold data such as custom classes and views and keep them during orientations changes and are only lost once the Activity is destroyed.

Android View Models

You can then code in a more "permanent" storage option say using SharedPreferences, files, sqlite when the Activity is destroyed. The persisted data can then be fetched and populate the ViewModel in the onAttatch method.

Maybe have a read of this to determine your requirements:

Android - Saving UI states.

Jcov
  • 2,122
  • 2
  • 21
  • 32