片段 addToBackStack() 和 popBackStackImmediate() 不起作用
Posted
技术标签:
【中文标题】片段 addToBackStack() 和 popBackStackImmediate() 不起作用【英文标题】:Fragment addToBackStack() and popBackStackImmediate() not working 【发布时间】:2014-12-28 21:35:53 【问题描述】:我目前正在使用一个ActionBarActivity
和多个Fragments
构建android (14 ListFragment 和MapFragment
,它们在单个@987654326 中交换@视图。
ActionBarActivity 自动替换/提交片段 A。然后,当用户点击按钮时,托管 Activity 替换/提交新的不同片段 B。我的目标是让用户在按下后立即返回片段 A后退按钮。
现在有一些代码。
主活动
public class MainActivity extends ActionBarActivity implements StopFragment.OnFragmentInteractionListener,
StopItemFragment.OnFragmentInteractionListener
...
@Override
protected void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
fragmentManager = getFragmentManager();
fragmentManager.enableDebugLogging(true);
...
if (fragmentManager.findFragmentById(R.id.content_frame) == null)
StopItemFragment list = StopItemFragment.newInstance(null); //A - extends ListFragment
fragmentManager.beginTransaction()
.replace(R.id.content_frame, list)
.addToBackStack(null)
.commit();
...
@Override
public void onFragmentInteraction(String id)
selectItem(Integer.parseInt(id));
private void selectItem(int position)
StopFragment fragment = StopFragment.newInstance(null, null); //B - extends Fragment
...
fragmentManager.beginTransaction()
.replace(R.id.content_frame, fragment)
.commit();
...
问题
即使调用addToBackStack()
,当我在fragment B时,我也无法回到fragment A。MainActivity被直接关闭。
然而,我试图自己管理后台堆栈,但没有运气。我可以看到片段在堆栈上,但是如果我调用popBackStackImmediate()
,片段 A 会弹出并且片段事务不会执行。 (第一次后按没有任何反应,第二次活动关闭)
我还附上了 FragmentManager logcat:http://pastebin.com/hFLHprL8
【问题讨论】:
【参考方案1】:对于那些仍在寻找解决方案的人。
在主Activity
类(托管片段)中,只需覆盖onBackPressed()
。
@Override
public void onBackPressed()
if (getFragmentManager().getBackStackEntryCount() > 0 )
getFragmentManager().popBackStack();
else
super.onBackPressed();
fragment中没有onBackPressed()
方法,该方法只针对activity
。所以,当我们按下返回键时,会显示activity
的默认行为,即
你要么去以前的活动(如果有的话)要么去应用程序 将退出。
现在我们需要重写这个方法来告诉activity
,当我们按下返回键时,如果返回堆栈中有任何碎片,则将它们弹出(这就是addToBackStack()
出现的时候)。否则遵循默认行为。
【讨论】:
谢谢。我想知道为什么android文档没有提到这个重要的东西?或者我只是想念它......【参考方案2】:试试这个(注意 add 而不是 replace 用于 fragmentA,addToBackStack() 用于 fragmentB)
StopItemFragment list = StopItemFragment.newInstance(null); //A - extends ListFragment
fragmentManager.beginTransaction()
.add(R.id.content_frame, list)
.commit();
和
StopFragment fragment = StopFragment.newInstance(null, null); //B - extends Fragment
...
fragmentManager.beginTransaction()
.replace(R.id.content_frame, fragment)
.addToBackStack("FragmentB")
.commit();
【讨论】:
这样我添加了堆栈片段 B 而不是 A。来自FragmentTransaction
文档:addToBackStack(): Add this transaction to the back stack. This means that the transaction will be remembered after it is committed, and will reverse its operation when later popped off the stack.
【参考方案3】:
我不得不手动致电FragmentManager
中的beginTransaction()
和commit()
。
通过覆盖onBackPressed()
解决:
@Override
public void onBackPressed()
...
if (fragmentManager.getBackStackEntryCount() > 1)
fragmentManager.popBackStackImmediate();
fragmentManager.beginTransaction().commit();
else
//handle finish
finish(); // Closes app
【讨论】:
popBackStackImmediate
比popBackStack
慢,为了避免性能问题,尽可能使用popBackStack
。【参考方案4】:
如果您正在为 addToBackStack() 和 popBackStack() 苦苦挣扎,那么只需使用
FragmentTransaction ft =getSupportFragmentManager().beginTransaction();
ft.replace(R.id.content_frame, new HomeFragment(), "Home");
ft.commit();`
在 OnBackPressed() 中的 Activity 中按标签找出片段,然后做你的事情
Fragment home = getSupportFragmentManager().findFragmentByTag("Home");
if (home instanceof HomeFragment && home.isVisible())
// do you stuff
更多信息https://github.com/DattaHujare/NavigationDrawer 我从不使用 addToBackStack() 来处理片段。
【讨论】:
【参考方案5】:popBackStack()
和popBackStackImmediatly()
的原因是您没有将该片段(您想要弹出的片段)添加到 backStack。为此,您必须在进行事务时调用 addToBackStack() 以添加/替换您的片段。
【讨论】:
【参考方案6】:首先,我想非常感谢突出显示的 [Nick] 的回答(低声誉无法在下面发表评论),因为它帮助我知道实际上有一些东西没有在Android 文档。
其次,现在是 2019 年,在 Androidx 的 Preferences 中以类似的方式磕磕绊绊后,我找了很长时间都找不到任何东西,直到我同时检查了这个问题和一个 official sample code in Kotlin,这个问题导致了线索和示例代码的方式实际上是我的解决方案,就像一个非常小的覆盖的魅力,希望它对那些正在寻找官方解决方案的人也有帮助
@Override
public boolean onSupportNavigateUp()
if (getSupportFragmentManager().popBackStackImmediate())
return true;
return super.onSupportNavigateUp();
Aforementioned code in Java (Screenshot)
附:在使用了至少 5 年以上之后,我在 stacksoverflow 上的第一个答案 ^^
【讨论】:
以上是关于片段 addToBackStack() 和 popBackStackImmediate() 不起作用的主要内容,如果未能解决你的问题,请参考以下文章
android fragment addToBackStack(null):如何将同一个片段添加到堆栈中一次?