在活动

时间:2017-01-12 13:27:12

标签: android android-fragments fragment savestate fragment-lifecycle

我正在处理一个应用程序,有一个特定的事情困扰着我。我们只说我有一个活动和2个片段。片段A和FragmentB以及FragmentA在活动开始时附加。

我希望在方向发生变化时保存片段数据和片段状态。我已使用OnSavedInstanceState方法成功保存了片段数据。现在我想在活动中保存片段状态,这样如果发生方向改变,我想要在我的片段上(在我的情况下,FragmentA或FragmentB取决于在配置更改发生之前显示的片段)。

这就是我在活动中保存片段状态的方式:

 @Override
protected void onSaveInstanceState(Bundle outState) {
    // Save the values you need into "outState"
    super.onSaveInstanceState(outState);
    outState.putLong(SS_DATE, userDate.getTime());

    android.support.v4.app.FragmentManager manager = getSupportFragmentManager();
    Fragment currentFragment = this.getSupportFragmentManager().findFragmentById(R.id.content_container);
    manager.putFragment(outState, "currentFragment", currentFragment);
}

这就是我在检索方向发生变化时检索我的片段的方式:

  @Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
    super.onRestoreInstanceState(savedInstanceState);

    FragmentManager manager = getSupportFragmentManager();
    @SuppressLint("CommitTransaction")
    FragmentTransaction transaction = manager.beginTransaction();

    if (savedInstanceState != null) {
        Fragment MyFragment = (Fragment) manager.getFragment(savedInstanceState, "currentFragment");

        if (MyFragment instanceof FragListStudentsAttendance) {
            Log.v("onRestore", FragListStudentsAttendance.TAG);


        }else if (MyFragment instanceof FragGetClassesForAttendance){
            Log.v("onRestore", FragGetClassesForAttendance.TAG);
            if(MyFragment!=null) {
                mFragGetClassesForAttendance = (FragGetClassesForAttendance) MyFragment;
            }else{


     mFragGetClassesForAttendance = new FragGetClassesForAttendance();
            FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
//            mFragGetClassesForAttendanceNew.setRetainInstance(true);
//            transaction.replace(R.id.content_ssadmin_container, mFragGetClassesForAttendanceNew, "FragGetClassesForAttendance").addToBackStack(null);
            transaction.add(R.id.content_ssadmin_container, mFragGetClassesForAttendance, FragGetClassesForAttendance.TAG);
            //transaction.replace(R.id.newEnrollmentMainContainer, mFragNewEnrollmentResults).addToBackStack("FragNewEnrollments");
            transaction.commit();
            mFragGetClassesForAttendance.setDate(userDate);
            }
        }
    }

}

立即 场景1: 如果我在片段A上并且我旋转设备,那么每件事情都应该正常工作。就像片段有web服务一样,它将数据加载到listview中,所以我检查数据是否存在,然后就不需要运行Web服务了,而且现在正在运行

场景2: 如果我在片段B上并且方向改变发生一切正常,因为它应该在片段B上。现在当我按后退按钮片段A再次被调用并且所有数据也来自服务。我认为这不应该发生,因为它应该在 BackStack 中并且它的数据被保存了。那我现在该怎么办呢?

场景3:在FragmentB上我注意到当我旋转设备时,FragmentA的saveInstanceState函数也会被调用。为什么会这样?我在哪里用FragmentA替换FragmentB?

一些混淆:

让我谈谈一些混淆,也许有人向我清楚,虽然我已经搜索并阅读了很多关于片段和活动生命周期的内容, 实际上我想保存每个活动的数据和片段在设备轮换上。我知道怎么做活动(如何保存状态)所以我也知道如何在片段中保存(保存片段视图的状态)现在我很困惑如何告诉活动哪个片段显示以及哪个片段在配置后去变化(轮换)?如果我在FragmentB上,FragmentA会发生什么呢?它会在后台一次又一次地连接和分离吗?

1 个答案:

答案 0 :(得分:1)

我遇到了你的问题和困惑。我认为片段的生命周期令你感到困惑。事实上它会让你感到困惑。

您需要了解不同的情况。  1.片段处于前景时的生命周期(与活动连接和分离)。请仔细观察所有会调用的方法,即OnSaveInstance,onCreateView,OnDestroyView,onDestroy  2.在背景中的片段生命周期(观察上述方法)  3.将碎片生命周期添加到后台堆叠(而不是前台)

我很确定你对点号3感到困惑。当片段被添加到backstack时,它永远不会被破坏。因此,旋转设备两次会将ffragment数据设置为null。我认为您正在恢复ActivityCreated或onViewCreated上的数据,

我建议你恢复oncreate中的片段数据。当你的片段从后台堆栈回到前台时,这将对你有用。

示例

    private List<String> mCountries;</pre>
@Override
public void onCreate(Bundle savedInstanceState)
{
    if (savedInstanceState != null)
    {
        // Populate countries from bundle
    }
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
    View view = inflater.inflate(R.layout.fragment_countries, container, false);

    if (mCountries == null)
    {
        // Populate countries by calling AsyncTask
    }

    return view;
}

public void onSaveInstanceState(Bundle outState)
{
    // Save countries into bundle
}

希望这会清除你的困惑。