隐藏片段的生命周期

Lifecycle of hidden fragment

我想了解activity生命周期和片段生命周期在Android中的交互,所以我决定开始一个新项目并从this page复制代码。
] 然后我认为,为了提高我的理解力,在平板电脑上对其进行测试、切换其方向并查看会发生什么(尽管可能并非为此目的)会很有用。 通过 logcat 我跟踪了在 activity 和国家片段上触发的主要事件,例如在 Activity Oncreate 我写:

Log.d("TAG", "Activity: 1.onCreate");

这是我从纵向视图开始然后旋转时得到的结果:

TAG: Activity: 1.onCreate
TAG: Activity: 2.onStart
TAG: ## ContryFrag: 1.onAttach
TAG: ## ContryFrag: 2.onCreateView
TAG: ## ContryFrag: 3.onStart
TAG: Activity: 3.onResume
TAG: ## ContryFrag: 4.onResume
TAG: Activity: -3.onPause
TAG: ## ContryFrag: -4.onPause
TAG: Activity: -2.onStop
TAG: ## ContryFrag: -3.onStop
TAG: Activity: -1.onDestroy
TAG: ## ContryFrag: -2.onDestroyView
TAG: ## ContryFrag: -1.onDetach
TAG: Activity: 1.onCreate
TAG: ## ContryFrag: 1.onAttach
TAG: ## ContryFrag: 1.onAttach
TAG: ## ContryFrag: 2.onCreateView
TAG: Activity: 2.onStart
TAG: ## ContryFrag: 2.onCreateView
TAG: ## ContryFrag: 3.onStart
TAG: ## ContryFrag: 3.onStart
TAG: Activity: 3.onResume
TAG: ## ContryFrag: 4.onResume
TAG: ## ContryFrag: 4.onResume

似乎在纵向视图中通过 FragmentManager 添加的片段在旋转后仍然重新创建,尽管它之前是分离的。恢复它的事件链再次跟随,即使它不会显示。
你能帮我理解这里发生了什么吗?

编辑

当我检查片段是否为 InLayout() 时

Log.d("TAG", "## ContryFrag: 1.onAttach /" + isInLayout() );

我发现旋转后有两个碎片:一个是旋转创建的,另一个似乎是前一个 activity 的剩余部分(不应该是)。

TAG: Activity: 1.onCreate
TAG: ## ContryFrag: 1.onAttach /false
TAG: ## ContryFrag: 1.onAttach /true
TAG: ## ContryFrag: 2.onCreateView /true
TAG: Activity: 2.onStart
TAG: ## ContryFrag: 2.onCreateView /false
TAG: ## ContryFrag: 3.onStart /false
TAG: ## ContryFrag: 3.onStart /true
TAG: Activity: 3.onResume
TAG: ## ContryFrag: 4.onResume /false
TAG: ## ContryFrag: 4.onResume /true

编辑 2

这是我用来获取 onSelectedCountry(String country) 的虚拟代码,未提供:

public void onSelectedCountry(String country)
{
    String[] x = {country, "city0", "city1", "city2", "city3", "city4", "city5"};
    adapter.clear();
    adapter.addAll(x);
}

编辑 3

这里是my code。抱歉耽搁了,这是我第一次使用 github。

您似乎没有使用片段的前一个实例。 当 Activity 由于配置更改而重新启动时,Android 会保留 Fragment 布局和关联的返回堆栈。 看起来当 Activity 重新创建时,会创建一个新片段。 尝试将以下代码添加到 Activity 的 onCreate:

@Override
public void onCreate(Bundle savedInstanceState) {

        ...    

    ContryFrag fragment = (ContryFrag) mFragmentManager.findFragmentById(R.id.fragment_container); 

    if (fragment == null) {
        FragmentTransaction fragmentTransaction = mFragmentManager.beginTransaction();
        fragmentTransaction.add(R.id.fragment_container, new ContryFrag());
        fragmentTransaction.commit();
    }
}

并删除片段创建代码。

Fragment 添加到 FragmentManager 后,它会保留在那里,直到您手动将其删除或直到 Activity 永久完成。 (重新启动 Activity 例如设备旋转时发生的情况不会导致它完成)

旋转设备不会清除碎片。如果您在 Activity 生命周期中的任何时候创建一个新的 Fragment 并将其添加到 FragmentManager 而没有首先检查 Fragment 是否已经存在于 FragmentManager ,每次您执行任何导致 Activity 重新启动的操作时,您只需添加一个新的 Fragment

例如,此代码应只允许添加您的片段的一个副本。

protected void onResume() {

    String TAG = "COUNTRYFRAG";

    CountryFrag f = (CountryFrag) getSupportFragmentManager().findFragmentByTag(TAG);

    if (f == null) {
        f = new CountryFrag();
        getSupportFragmentManager().beginTransaction()
                .add(f, TAG)
                .commit();
    }

    int count = getSupportFragmentManager().getFragments().size();
    Log.v("FRAGS", "There are " + count + "fragments in the fragment manager.");

}

而这个会在您每次旋转设备时添加一个新的。

protected void onResume() {

    String TAG = "COUNTRYFRAG";

        CountryFrag f = new CountryFrag();
        getSupportFragmentManager().beginTransaction()
                .add(f, TAG)
                .commit();

    int count = getSupportFragmentManager().getFragments().size();
    Log.v("FRAGS", "There are " + count + "fragments in the fragment manager.");

}

link 处的代码似乎使用 savedInstanceState 的存在来确定是添加片段还是从方法中 return。这是不可靠的,因为您可能没有在状态中保存任何内容,因此它可能始终为空。最好具体检查是否已经添加了Fragment。

if (savedInstanceState != null) 
            return;

链接的文章在布局 xml 中定义了片段。您在 github 中的代码正在按代码创建和添加片段。你是把这两个一起用吗?