Android 片段 onResume() 和 onPause() 不会在 backstack 上调用
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11326155/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Fragment onResume() & onPause() is not called on backstack
提问by Krishnabhadra
I have multiple fragment inside an activity. On a button click I am starting a new fragment, adding it to backstack. I naturally expected the onPause()
method of current Fragment and onResume()
of new Fragment to be called. Well it is not happening.
我在一个活动中有多个片段。单击按钮后,我将开始一个新片段,并将其添加到 backstack。我自然期待onPause()
current Fragment 和onResume()
new Fragment 的方法被调用。嗯,它没有发生。
LoginFragment.java
登录片段.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
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();
}
}
What I expected, was,
我所期望的是,
- When button is clicked, LoginFragmentgets replaced with
HomeFragment,
onPause()
of LoginFragment, andonResume()
of HomeFragmentgets called - When back is pressed, HomeFragmentis poped out and LoginFragmentis
seen, and
onPause()
of HomeFragmentandonResume()
of LoginFragmentgets called.
- 当用户点击按钮,LoginFragment被替换为
HomeFragment,
onPause()
的LoginFragment和onResume()
的 HomeFragment被调用 - 当被压回,HomeFragment是POP操作并LoginFragment看到,和
onPause()
的HomeFragment和onResume()
的LoginFragment被调用。
What I am getting is,
我得到的是,
- When button is clicked, HomeFragmentis correctly replacing LoginFragment, onResume() of HomeFragmentis called, but onPause() of LoginFragmentis never called.
- When back pressed, HomeFragmentis correctly popping to reveal LoginFragment, onPause() of HomeFragmentgets called, but onResume() of LoginFragmentnever gets called.
- 当用户点击按钮,HomeFragment正确更换 LoginFragment,的onResume()的HomeFragment被调用,但在onPause(的)LoginFragment永远不会被调用。
- 当按下回来,HomeFragment正确弹出透露 LoginFragment,在onPause()的HomeFragment被调用,但的onResume(的)LoginFragment不会被调用。
Is this the normal behaviour? Why is onResume()
of LoginFragmentnot getting called when I press the back button.
这是正常行为吗?为什么是onResume()
的LoginFragment当我按下后退按钮没有得到调用。
采纳答案by Sagar Waghmare
The fragments onResume()
or onPause()
will be called only when the Activities onResume()
or onPause()
is called.
They are tightly coupled to the Activity
.
片段onResume()
oronPause()
只会在活动onResume()
oronPause()
被调用时被调用。它们与Activity
.
Read the Handling the Fragment Lifecycle section of this article.
阅读本文的处理片段生命周期部分。
回答by Gopal
- Since you have used
ft2.replace()
,FragmentTransaction.remove()
method is called and theLoginfragment
will be removed. Refer to this. SoonStop()
ofLoginFragment
will be called instead ofonPause()
. (As the new fragment completely replaces the old one). - But since you have also
used
ft2.addtobackstack()
, the state of theLoginfragment
will be saved as a bundle and when you click back button fromHomeFragment
,onViewStateRestored()
will be called followed byonStart()
ofLoginFragment
. So eventuallyonResume()
won't be called.
- 由于您使用了
ft2.replace()
,FragmentTransaction.remove()
方法被调用并且Loginfragment
将被删除。参考这个。所以onStop()
ofLoginFragment
将被调用而不是onPause()
. (因为新片段完全取代了旧片段)。 - 但由于您也使用过
ft2.addtobackstack()
,the 的状态Loginfragment
将被保存为一个包,当您单击 from 后退按钮时HomeFragment
,onViewStateRestored()
将被调用,然后是onStart()
ofLoginFragment
。所以最终onResume()
不会被调用。
回答by aaronmarino
Here's my more robust version of Gor's answer (using fragments.size()is unreliable due to size not being decremented after fragment is popped)
这是我更强大的 Gor 答案版本(使用 fragment.size() 是不可靠的,因为在弹出片段后大小没有减少)
getFragmentManager().addOnBackStackChangedListener(new FragmentManager.OnBackStackChangedListener() {
@Override
public void onBackStackChanged() {
if (getFragmentManager() != null) {
Fragment topFrag = NavigationHelper.getCurrentTopFragment(getFragmentManager());
if (topFrag != null) {
if (topFrag instanceof YourFragment) {
//This fragment is being shown.
} else {
//Navigating away from this fragment.
}
}
}
}
});
And the 'getCurrentTopFragment' method:
和“getCurrentTopFragment”方法:
public static Fragment getCurrentTopFragment(FragmentManager fm) {
int stackCount = fm.getBackStackEntryCount();
if (stackCount > 0) {
FragmentManager.BackStackEntry backEntry = fm.getBackStackEntryAt(stackCount-1);
return fm.findFragmentByTag(backEntry.getName());
} else {
List<Fragment> fragments = fm.getFragments();
if (fragments != null && fragments.size()>0) {
for (Fragment f: fragments) {
if (f != null && !f.isHidden()) {
return f;
}
}
}
}
return null;
}
回答by Bersh
If you really want to replace fragment inside other fragment you should use Nested Fragments.
如果你真的想替换其他片段中的片段,你应该使用Nested Fragments。
In your code you should replace
在您的代码中,您应该替换
final FragmentManager mFragmentmanager = getFragmentManager();
with
和
final FragmentManager mFragmentmanager = getChildFragmentManager();
回答by Gor
getFragmentManager().addOnBackStackChangedListener(new FragmentManager.OnBackStackChangedListener() {
@Override
public void onBackStackChanged() {
List<Fragment> fragments = getFragmentManager().getFragments();
if (fragments.size() > 0 && fragments.get(fragments.size() - 1) instanceof YoureFragment){
//todo if fragment visible
} else {
//todo if fragment invisible
}
}
});
but be careful if more than one fragment visible
但如果有多个片段可见,请小心
回答by PepitoGrillo
I have a code very similar to yours and if it works onPause () and onResume (). When changing the fragment, these functions are activated respectively.
我有一个与你的代码非常相似的代码,如果它在 onPause () 和 onResume () 上工作。当改变片段时,这些功能分别被激活。
Code in fragment:
片段中的代码:
@Override
public void onResume() {
super.onResume();
sensorManager.registerListener(this, proximidad, SensorManager.SENSOR_DELAY_NORMAL);
sensorManager.registerListener(this, brillo, SensorManager.SENSOR_DELAY_NORMAL);
Log.e("Frontales","resume");
}
@Override
public void onPause() {
super.onPause();
sensorManager.unregisterListener(this);
Log.e("Frontales","Pause");
}
Log when change of fragment:
更改片段时记录:
05-19 22:28:54.284 2371-2371/madi.cajaherramientas E/Frontales: resume
05-19 22:28:57.002 2371-2371/madi.cajaherramientas E/Frontales: Pause
05-19 22:28:58.697 2371-2371/madi.cajaherramientas E/Frontales: resume
05-19 22:29:00.840 2371-2371/madi.cajaherramientas E/Frontales: Pause
05-19 22:29:02.248 2371-2371/madi.cajaherramientas E/Frontales: resume
05-19 22:29:03.718 2371-2371/madi.cajaherramientas E/Frontales: Pause
Fragment onCreateView:
片段 onCreateView:
View rootView;
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
rootView = inflater.inflate(R.layout.activity_proximidad, container, false);
ButterKnife.bind(this,rootView);
inflar();
setTextos();
return rootView;
}
Action when I pulse back (in the activity where I load the fragment):
当我回跳时的动作(在我加载片段的活动中):
@Override
public void onBackPressed() {
int count = getFragmentManager().getBackStackEntryCount();
if (count == 0) {
super.onBackPressed();
} else {
getFragmentManager().popBackStack();
}
}
回答by Guillermo De Juan
What i do in child fragment:
我在子片段中做什么:
@Override
public void onDetach() {
super.onDetach();
ParentFragment pf = (ParentFragment) this.getParentFragment();
pf.onResume();
}
And then override onResume on ParentFragment
然后在 ParentFragment 上覆盖 onResume
回答by álvaro Agüero
I use in my activity - KOTLIN
我在我的活动中使用 - KOTLIN
supportFragmentManager.addOnBackStackChangedListener {
val f = supportFragmentManager.findFragmentById(R.id.fragment_container)
if (f?.tag == "MyFragment")
{
//doSomething
}
}
回答by Nickolaus
You simple can'tadd a fragment to a fragment. This needs to happen in the FragmentActivity. I assume you are creating the LoginFragment in a FragmentActivity, so in order to get this working you need to add the HomeFragment via the FragmentActivity when the login closes.
您不能简单地将片段添加到片段中。这需要发生在 FragmentActivity 中。我假设您正在 FragmentActivity 中创建 LoginFragment,因此为了使其正常工作,您需要在登录关闭时通过 FragmentActivity 添加 HomeFragment。
The general point is that you need a FragmentActivity class from where you add each Fragment to the FragmentManager. It is not possibleto do this inside a Fragment class.
一般的观点是您需要一个 FragmentActivity 类,您可以从中将每个 Fragment 添加到 FragmentManager。这是不可能做到这一点片段类中。
回答by Dustin
If you add the fragment in XML, you can't swap them dynamically. What happens is they overly, so they events don't fire as one would expect. The issue is documented in this question. FragmenManager replace makes overlay
如果在 XML 中添加片段,则无法动态交换它们。发生的事情是他们过度,所以他们的事件不会像人们预期的那样触发。这个问题记录在这个问题中。FragmenManager 替换使覆盖
Turn middle_fragment into a FrameLayout, and load it like below and your events will fire.
将 middle_fragment 转换为 FrameLayout,然后像下面那样加载它,您的事件就会触发。
getFragmentManager().beginTransation().
add(R.id.middle_fragment, new MiddleFragment()).commit();