我在一个活动中有多个片段 . 在按钮上单击我开始一个新片段,将其添加到backstack . 我自然期望调用当前片段的 onPause()
方法和新片段的 onResume()
. 好吧,它没有发生 .
LoginFragment.java
public class LoginFragment extends Fragment{
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
final View view = inflater.inflate(R.layout.login_fragment, container, false);
final FragmentManager mFragmentmanager = getFragmentManager();
Button btnHome = (Button)view.findViewById(R.id.home_btn);
btnHome.setOnClickListener(new View.OnClickListener() {
public void onClick(View view){
HomeFragment fragment = new HomeFragment();
FragmentTransaction ft2 = mFragmentmanager.beginTransaction();
ft2.setCustomAnimations(R.anim.slide_right, R.anim.slide_out_left
, R.anim.slide_left, R.anim.slide_out_right);
ft2.replace(R.id.middle_fragment, fragment);
ft2.addToBackStack("");
ft2.commit();
}
});
}
@Override
public void onResume() {
Log.e("DEBUG", "onResume of LoginFragment");
super.onResume();
}
@Override
public void onPause() {
Log.e("DEBUG", "OnPause of loginFragment");
super.onPause();
}
}
HomeFragment.java
public class HomeFragment extends Fragment{
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
final View view = inflater.inflate(R.layout.login_fragment, container, false);
}
@Override
public void onResume() {
Log.e("DEBUG", "onResume of HomeFragment");
super.onResume();
}
@Override
public void onPause() {
Log.e("DEBUG", "OnPause of HomeFragment");
super.onPause();
}
}
我所期待的是,
-
单击按钮时, LoginFragment 替换为 HomeFragment ,
onPause()
为 LoginFragment ,onResume()
被 HomeFragment 调用 -
当按下后退时, HomeFragment 被输出并且看到 LoginFragment ,并且_2452100_的_2452100_和
onResume()
被_2552202_调用 .
我得到的是,
-
单击按钮时, HomeFragment 正在替换 LoginFragment , HomeFragment 的onResume()被调用,但 LoginFragment 的onPause()从未被调用 .
-
当后退时, HomeFragment 正确弹出以显示 LoginFragment , HomeFragment 的onPause()被调用,但 LoginFragment 的onResume()从未被调用 .
这是正常行为吗?当按下后退按钮时,为什么 LoginFragment 的 onResume()
未被调用 .
17 回答
调用
ft.replace
应该触发onPause(替换片段)和onResume(替换片段) .我注意到你的代码在home片段上膨胀了
login_fragment
,并且也没有返回onCreateView中的视图 . 如果这些是拼写错误,您能否说明如何从您的活动中调用这些片段?只有在调用Activities
onResume()
或onPause()
时才会调用片段onResume()
或onPause()
. 它们与Activity
紧密耦合 .阅读Handling the Fragment Lifecycle section of this article .
由于您已使用
ft2.replace()
,因此将调用FragmentTransaction.remove()
方法并删除Loginfragment
. 请参阅this . 所以LoginFragment
的LoginFragment
将被调用而不是onPause()
. (因为新片段完全取代旧片段) .但由于您还使用了
ft2.addtobackstack()
,Loginfragment
的状态将保存为一个包,当您单击HomeFragment
的后退按钮时,将调用onViewStateRestored()
,然后调用LoginFragment
的onStart()
. 所以最终onResume()
将不会被调用 .如果你真的想要替换其他片段中的片段,你应该使用Nested Fragments .
在您的代码中,您应该替换
同
根据@Gor的回答,我在Kotlin写了类似的内容 . 将此代码放在活动的
onCreate()
中 . 它适用于一个可见的片段 . 如果你有ViewPager
片段,它将调用ViewPager
的片段,而不是之前的片段 .阅读https://medium.com/@elye.project/puzzle-fragment-stack-pop-cause-issue-on-toolbar-8b947c5c07c6后,我明白在许多情况下,使用
replace
而不是add
附加新片段会更好 . 所以在某些情况下onResume
的需求将会消失 .这是我更强大的Gor的答案版本(使用fragments.size()是不可靠的,因为弹出片段后大小没有减少)
'getCurrentTopFragment'方法:
但如果有多个片段可见,请小心
我有一个非常类似于你的代码,如果它工作onPause()和onResume() . 更改片段时,分别激活这些功能 .
片段代码:
更改片段时记录:
片段onCreateView:
我回击时的动作(在我加载片段的活动中):
你很简单 can't 将片段添加到片段中 . 这需要在FragmentActivity中发生 . 我假设您正在FragmentActivity中创建LoginFragment,因此为了使其正常工作,您需要在登录关闭时通过FragmentActivity添加HomeFragment .
一般来说,您需要一个FragmentActivity类,从而将每个Fragment添加到FragmentManager . 在Fragment类中执行此操作是 not possible .
如果以XML格式添加片段,则可以像预期的那样触发 . 这个问题记录了这个问题 . FragmenManager replace makes overlay
将middle_fragment转换为FrameLayout,然后像下面一样加载它,你的事件就会触发 .
你可以试试这个,
第1步:覆盖活动中的Tabselected方法
第2步:使用静态方法在片段中执行您想要的操作,
我在子片段中做了什么:
然后在ParentFragment上覆盖onResume
片段必须始终嵌入到活动中,片段的生命周期直接受主机活动生命周期的影响 . 例如,当活动暂停时,其中的所有片段也都会暂停,当活动被破坏时,所有片段也都会被破坏
onPause()
方法适用于您可以使用的活动类:出于同样的目的..
Follow the below steps, and you shall get the needed answer
1-对于两个片段,创建一个新的抽象父片段 .
2-添加应由两者实现的自定义抽象方法 .
3-在替换第二个实例之前从当前实例调用它 .
虽然使用不同的代码,但我遇到了与OP相同的问题,因为我最初使用过
代替
使用“替换”时,从第二个片段返回时会重新创建第一个片段,因此也会调用onResume() .
在创建片段事务时,请确保添加以下代码 .
还要确保在将事务添加到backstack后提交事务