9

整数を永続化するために使用される SeekBar を持つ独自のカスタム DialogPreference サブクラスを実装しています。onSaveInstanceState()とに何を入れる必要があるかについて少し混乱していますonRestoreInstanceState()。具体的には、ユーザーが操作する UI ウィジェット (私の場合は SeekBar ウィジェット) を更新する必要がありますonRestoreInstanceState()か?

私が混乱している理由は、ここの API doc 記事で、これを行うように指示されているためです。

@Override
protected Parcelable onSaveInstanceState() {
    final Parcelable superState = super.onSaveInstanceState();
    if (isPersistent()) {
        return superState;
    }

    final SavedState myState = new SavedState(superState);
    myState.value = mNewValue; //<------------ saves mNewValue
    return myState;
}

@Override
protected void onRestoreInstanceState(Parcelable state) {
    if (state == null || !state.getClass().equals(SavedState.class)) {
        super.onRestoreInstanceState(state);
        return;
    }

    SavedState myState = (SavedState) state;
    super.onRestoreInstanceState(myState.getSuperState());
    mNumberPicker.setValue(myState.value); //<------------ updates the UI widget, not mNewValue!
}

しかし、いくつかの公式の Android Preference クラス ( EditTextPreferenceおよびListPreference ) のソースを見ると、UI ウィジェットは で更新されていませんonRestoreInstanceState()。Preference の基になる値のみが (上記の例では、 になりますmNewValue)。

EditTextPreference の関連ソースは次のとおりです。

@Override
protected Parcelable onSaveInstanceState() {
    final Parcelable superState = super.onSaveInstanceState();
    if (isPersistent()) {
        return superState;
    }

    final SavedState myState = new SavedState(superState);
    myState.value = getValue(); //<---- saves mValue
    return myState;
}

@Override
protected void onRestoreInstanceState(Parcelable state) {
    if (state == null || !state.getClass().equals(SavedState.class)) {
        super.onRestoreInstanceState(state);
        return;
    }

    SavedState myState = (SavedState) state;
    super.onRestoreInstanceState(myState.getSuperState());
    setValue(myState.value); //<---- updates mValue, NOT the UI widget!
}

それで、コンセンサスは何ですか?UIウィジェットをどこで更新することになっていますか(まったく更新することになっている場合...)?

4

1 に答える 1

4

さて、いくつかの実験の後、内部の UI ウィジェットを更新するのはonRestoreInstanceState()適切nullではないようです。彼らがそれを提案する理由がわかりません。おそらく、Preference をサブクラス化する場合はそれを行う必要がありますが、DialogPreference をサブクラス化する場合に従うべきさまざまな規則があります...? ListPreference と EditTextPreference は DialogPreference のサブクラスであるため、少なくともそれを行わない理由を説明できます。

実際、私が発見したことによると、UI ウィジェットを更新する必要はまったくありません。状態管理を処理する独自の保存/復元メソッドが必要です。たとえば、SeekBar ウィジェットを使用して作成した DialogPreference サブクラスの抜粋を次に示します。

@Override
protected Parcelable onSaveInstanceState() {
    final Parcelable superState = super.onSaveInstanceState();

    final SavedState myState = new SavedState(superState);
    myState.maxValue = getMaxValue(); //<---- saves mMaxValue
    myState.value = getValue(); //<---- saves mValue
    return myState;
}

@Override
protected void onRestoreInstanceState(Parcelable state) {
    if (state == null || !state.getClass().equals(SavedState.class))
    {
        super.onRestoreInstanceState(state);
        return;
    }

    SavedState myState = (SavedState) state;
    setMaxValue(myState.maxValue); //<---- updates mMaxValue
    setValue(myState.value); //<---- updates mValue
    super.onRestoreInstanceState(myState.getSuperState());
}

ご覧のとおり、どこでも SeekBar ウィジェットを更新することはありません。SeekBar は、その状態をすべて単独で保存/復元します。

また、Android 開発者向けドキュメントで提案されている内容とは若干の相違があることにも気付くでしょう。状態を保存する前に DialogPreference が永続的であるかどうかを確認しませmValuemMaxValuesuper.onRestoreInstanceState()また、以前に呼び出されたときに機能しないことがわかったので、最後に呼び出します。

これらは、これまでの私の調査結果にすぎません。正しい方法はわかりませんが、上記の方法でうまくいくようです。

更新: @whatyouhide は、私の DialogPreference サブクラスでメソッドsetValueとメソッドがどのように見えるかを知りたがっています。setMaxValueどうぞ:

public void setValue(int value)
{
    value = Math.max(Math.min(value, mMaxValue), mMinValue);

    if (value != mValue)
    {
        mValue = value;
        persistInt(value);
        notifyChanged();
    }
}

public void setMaxValue(int maxValue)
{
    mMaxValue = maxValue;
    setValue(Math.min(mValue, mMaxValue));
}
于 2013-01-14T11:03:11.477 に答える