如何保存片段状态

时间:2018-12-16 13:22:18

标签: android

我有SettingActivity。它包含SettingFragment(具有ListPreference)和另一个AudioSamplingSeekBarFragment(具有我的自定义首选项)。当我在ListPreference中选择某些项目时,我将使用从ListPreference中选择的数据重新创建AudioSamplingSeekBarFragment。像这样:

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);
    }
}
}**

所以当我完全使用SettingActivity并再次进入我的AudioSamplingSeekBarFragment时,它不会保存状态。

我将片段放在SettingsActivity的onSaveInstanceState()中,就像他们在这里所说的: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));
}

并将特定数据保存在Fragment的onSaveInstanceState()中:

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);
}

我希望在这里恢复保存的数据:

@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) {

        }
    });
}
}

但这不起作用。

仅在案例布局中:

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>

1 个答案:

答案 0 :(得分:0)

据我所知,SavedInstanceState仅存储一捆数据。仅基本内容,例如字符串,整数等,不包含视图之类的内容。

我认为您应该真正使用ViewModel,因为它可以保存诸如自定义类和视图之类的数据,并在方向更改时保留它们,并且仅在Activity被销毁后才会丢失。

Android View Models

然后,在销毁Activity时,可以使用SharedPreferences,文件和sqlite在更“永久”的存储选项中进行编码。然后可以在onAttatch方法中获取持久数据并填充ViewModel。

也许要阅读一下以确定您的要求:

Android - Saving UI states.