在Activity onRestoreInstanceState()之前调用onCreateView()for Fragment

时间:2016-08-12 01:01:26

标签: android android-fragments

所以我有一个附加到活动的片段,我试图确保在旋转屏幕时(或任何会中断活动的事情)顺利进行。为此,我在活动中使用onSaveInstanceState和onRestoreInstanceState方法来保存我的活动存储的信息。

当创建my片段的视图时,片段会询问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()始终最后调用。这意味着在创建视图时片段无法访问活动的信息。

这应该发生吗?在恢复活动时,如何让我的片段视图使用活动中的信息?

2 个答案:

答案 0 :(得分:1)

更新回复:

阅读替代方案Passing data between a fragment and its container activity。另请参阅this

之前的回复修订:

请参阅this并尝试将您的代码置于onResume()中,并使视图无效或detach/attach the fragment作为快速解决方案,但不是the best solution,正如Alex Lockwood所说:

  

片段是可重复使用的UI组件。他们有自己的生命周期,   显示自己的视图,并定义自己的行为。你通常   不需要让你的活动陷入内部困境   片段的运作,如片段的行为应该是   自包含且独立于任何特定活动。

如果您之前确实需要代码,请覆盖下一个方法并直接保存/恢复片段中所需的数据:

/**
 * 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...;
}

创建这个,用于从bundle中检索所需的数据:

public void restoreInstanceState(Bundle savedInstanceState) {
    ... = savedInstanceState.get...
}
如果由于某种原因需要活动代码,请使用{p>或使用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()方法添加到活动中。

更多信息here以及定义接口here的替代解决方案。

答案 1 :(得分:1)

我认为最简单的方法是使用EventBus 您可以在重新创建活动时发送“msg”,并且您的片段的“目标方法”将获得此消息(msg是Object,它可以是一个包)。