隐藏片段的生命周期
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 中的代码正在按代码创建和添加片段。你是把这两个一起用吗?
我想了解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 中的代码正在按代码创建和添加片段。你是把这两个一起用吗?