簡體   English   中英

在Activity onRestoreInstanceState()之前調用Fragment的onCreateView()

[英]onCreateView() for Fragment being called before Activity onRestoreInstanceState()

因此,我在活動上附加了一個片段,我試圖確保屏幕旋轉時(或會中斷活動的任何事物)順利進行。 為此,我在活動中使用onSaveInstanceState和onRestoreInstanceState方法來保留活動中存儲的信息。

創建我的片段的視圖時,片段會向Activity詢問信息(這在片段的onCreateView()中):

ArrayList<String> picList = mListener.getPics();
ArrayList<String> descripList = mListener.getDescriptions();

為了使該片段創建視圖,它需要訪問picList和descripList,它們是活動的成員變量。 這些成員變量在onSaveInstanceState和onRestoreInstanceState中存儲和恢復。

protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    if(photoFile != null)
        outState.putString("photoFile", photoFile.getAbsolutePath());
    outState.putString("currentFragTag", currentFragTag);
    outState.putStringArrayList("picList", picList);
    outState.putStringArrayList("descripList", descripList);
}

@Override
protected void onRestoreInstanceState(Bundle saved) {
    super.onRestoreInstanceState(saved);
    if(saved.getString("photoFile") != null)
        photoFile = new File(saved.getString("photoFile"));
    currentFragTag = saved.getString("currentFragTag");
    picList = saved.getStringArrayList("picList");
    descripList = saved.getStringArrayList("descripList");
    currentFrag = getFragmentManager().findFragmentByTag(currentFragTag);
    changeFrag(currentFrag, currentFragTag);
}

問題是,在活動中調用onRestoreInstanceState()之前先調用onCreateView()。 我嘗試在片段中使用onActivityCreated(),但在onRestoreInstanceState()之前也曾調用過它。 附加了調試器后,旋轉屏幕時,始終會最后調用onRestoreInstanceState()。 這意味着在創建視圖時,該片段無法訪問活動的信息。

這應該發生嗎? 恢復活動時,如何讓片段的視圖使用活動中的信息?

更新的響應:

閱讀其他選擇在片段及其容器活動之間傳遞數據 另請參閱

先前的回應已修訂:

看到這個並嘗試將您的代碼放在onResume()中並使視圖無效或分離/附加該片段 ,這是一種快速解決方案,但不是Alex Lockwood所說的最佳解決方案

片段是可重用的UI組件。 他們有自己的生命周期,顯示自己的觀點,並定義自己的行為。 通常,您不需要使Activity混亂於Fragment的內部工作,因為Fragment的行為應該是獨立的,並且與任何特定的Activity無關。

如果您之前確實需要代碼,請覆蓋下一個方法,然后直接在片段中保存/還原所需的數據:

/**
 * Called when the fragment's activity has been created and this
 * fragment's view hierarchy instantiated.  It can be used to do final
 * initialization once these pieces are in place, such as retrieving
 * views or restoring state.  It is also useful for fragments that use
 * {@link #setRetainInstance(boolean)} to retain their instance,
 * as this callback tells the fragment when it is fully associated with
 * the new activity instance.  This is called after {@link #onCreateView}
 * and before {@link #onViewStateRestored(Bundle)}.
 *
 * @param savedInstanceState If the fragment is being re-created from
 * a previous saved state, this is the state.
 */
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
    super.onActivityCreated(savedInstanceState);
    if (savedInstanceState != null) {
        restoreInstanceState(savedInstanceState);
    }
}

/**
 * Called to ask the fragment to save its current dynamic state, so it
 * can later be reconstructed in a new instance of its process is
 * restarted.  If a new instance of the fragment later needs to be
 * created, the data you place in the Bundle here will be available
 * in the Bundle given to {@link #onCreate(Bundle)},
 * {@link #onCreateView(LayoutInflater, ViewGroup, Bundle)}, and
 * {@link #onActivityCreated(Bundle)}.
 *
 * <p>This corresponds to {@link Activity#onSaveInstanceState(Bundle)
 * Activity.onSaveInstanceState(Bundle)} and most of the discussion there
 * applies here as well.  Note however: <em>this method may be called
 * at any time before {@link #onDestroy()}</em>.  There are many situations
 * where a fragment may be mostly torn down (such as when placed on the
 * back stack with no UI showing), but its state will not be saved until
 * its owning activity actually needs to save its state.
 *
 * @param outState Bundle in which to place your saved state.
 */
@Override
public void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    outState.put...;
}

並創建一個,用於從包中檢索所需的數據:

public void restoreInstanceState(Bundle savedInstanceState) {
    ... = savedInstanceState.get...
}

或使用getActivity()方法直接從此處訪問某些方法或字段(如果出於某種原因需要活動代碼)。

/**
 * Return the {@link FragmentActivity} this fragment is currently associated with.
 * May return {@code null} if the fragment is associated with a {@link Context}
 * instead.
 */
final public FragmentActivity getActivity() {
    return mHost == null ? null : (FragmentActivity) mHost.getActivity();
}

例如: ((YourActivity) getActivity()).getPics();

並將getPics()方法添加到活動中。

進一步信息在這里和一個替代解決方案定義一個接口這里

我認為最簡單的方法是使用EventBus。
您可以在重新創建活動時發送“ msg”,並且片段的“ target方法”將獲取此msg(msg是Object,可以是一個包)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM