我已经在SO上做了一些阅读和搜索,但找不到清除当前活动堆栈的方法.我的应用程序的上下文是由后台服务/通知启动的活动.
想象一下,我的应用程序允许您组织人员列表.几个小时前,您正在"查看"活动中查看人员X,现在这是您的堆栈顶部.在将来的某个时刻,服务会触发并为人Y弹出一个新的"通知"活动.从那里你可以编辑人Y的详细信息.
当你完成这个活动时,弹出堆栈并最终查看人X将是一个令人困惑的用户体验.理想情况下,我想回到用户正在做的任何事情(电子邮件等...),或者至少我的应用程序的主页.
我尝试启动"通知",FLAG_ACTIVTY_NEW_TASK但似乎没有帮助:当任务完成时,它只是回到上一个任务.我想要的似乎是Android 3的新功能FLAG_ACTIVITY_CLEAR_TASK,这在之前的SDK中并不存在.
有没有人有建议去做到这一点?
我有一个问题,我无法在任何地方找到解决方案.
当我按下后退按钮时,我的应用程序不会返回到上一个片段,而是关闭活动.
我有一个显示4个片段的活动:[1],[2],[3],[4].我可以使用操作栏在前3个片段之间切换,我不想将它们添加到后台堆栈.
片段[4]是片段[3]中选择的项目的详细视图.当我按下[4]时,我想返回片段[3],而不是关闭应用程序.
过渡是以这种方式完成的,其中放置了碎片的活动:
private void replaceFragment(Fragment fragment, boolean toBackStack){
if(fragment != null){
FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction();
fragmentTransaction.replace(R.id.container, fragment);
if(toBackStack)
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
}
}
Run Code Online (Sandbox Code Playgroud)
除非转换是从[3]到[4],否则toBackStack始终为false.
如果我在每次转换中都将toBackStack传递给true,那么活动无论如何都会关闭.
我正在使用几个fragments来动态添加activity.一切正常,当我按下后退按钮时,fragments会去backstack.当resume它出现时,它会出现.但每次都在Resume,它正在重新创造fragment和呼唤onCreateView.我知道这是fragment生命周期的正常行为.
这是我的onCreateView:
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(
R.layout.competitive_programming_exercise, container, false);
return rootView;
}
Run Code Online (Sandbox Code Playgroud)
我想阻止那些fragment重新创作.我尝试过,onSavedInstanstate但没有任何工作.我怎么能做到这一点?
我刚刚实现了一种在我的应用程序中更改主题的方法.按下按钮可在SharedPreferences中设置值,然后重新创建活动,并且由于该标志而更改主题.
问题是如何处理后台堆栈.简单地重新创建活动并不好,因为按下硬件后退按钮将恢复之前的活动(旧主题仍然设置),而如果用户执行以下操作:
从活动A> B> C>按主题更改按钮>按硬件后退按钮开始
然后,我希望他们能够被带回活动B 与新的主题正确应用.到目前为止,我发现的最佳解决方案是根据对象层次结构重新创建backstack,如下所示:
Intent intent = new Intent();
intent.setClass(activity, activity.getClass());
TaskStackBuilder stackBuilder = TaskStackBuilder.create(activity);
stackBuilder.addNextIntentWithParentStack(intent);
stackBuilder.startActivities(new Bundle());
Run Code Online (Sandbox Code Playgroud)
但是我们的应用程序中的活动层次结构没有很好地定义(即C可以有多个父项),因此上面的代码可能导致用户在按下后退按钮后被带回到意外活动.
有没有一种干净的方法来重建基于实际的后栈而不是Activity层次结构的后栈?
我在MainActivity中使用底部导航栏来处理一些片段。这是用于在它们之间切换的代码:
private val mOnNavigationItemSelectedListener = BottomNavigationView.OnNavigationItemSelectedListener { item ->
if (item.isChecked &&
supportFragmentManager.findFragmentById(R.id.act_main_fragment_container) != null
)
return@OnNavigationItemSelectedListener false
val fragment =
when (item.itemId) {
R.id.navigation_home -> fragments[0]
R.id.navigation_bookings -> fragments[1]
R.id.navigation_messages -> fragments[2]
R.id.navigation_dashboard -> fragments[3]
R.id.navigation_profile -> fragments[4]
else -> fragments[0]
}
this replaceWithNoBackStack fragment
return@OnNavigationItemSelectedListener true
}
Run Code Online (Sandbox Code Playgroud)
方法replaceWithNoBackstack只是此的简写:
supportFragmentManager
?.beginTransaction()
?.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
?.replace(containerId, fragment)
?.commit()
Run Code Online (Sandbox Code Playgroud)
问题是,当我在它们之间更快地切换时,我的应用程序崩溃,但出现以下异常:
java.lang.IllegalStateException:仅在所有者的初始化阶段,必须在androidx的androidx.fragment.app.Fragment.performCreate(Fragment.java:2580)的androidx.savedstate.SavedStateRegistryController.performRestore(SavedStateRegistryController.java:59)上创建重新启动器。 androidx.fragment.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManagerImpl.java:1237)处于androidx.fragment.app.FragmentManagerImpl.moveToState(FragmentManagerImpl.java:1302)处的fragment.app.FragmentManagerManager.mpl.moveToState(FragmentManagerImpl.java:837) androidx.fragment.app.FragmentManagerImpl.executeOps(FragmentManagerImpl.java:2075)上的.fragment.app.BackStackRecord.executeOps(BackStackRecord.java:439),位于androidx.fragment.app.FragmentManagerImpl。在androidx.fragment.app上的executeOpsTogether(FragmentManagerImpl.java:1865)在androidx.fragment.app处的FragmentManagerImpl.removeRedundantOperationsAndExecute(FragmentManagerImpl.java:1820)在androidx.fragment.app.FragmentManagerImpl.execPendingActions(FragmentManagerImpl.java:1726)在androidx.fragment。 $ 2.run(FragmentManagerImpl.java:150)在android.os.Handler.handleCallback(Handler.java:789)在android.os.Handler.dispatchMessage(Handler.java:98)在android.os.Looper.loop(Looper .java:164),位于android.app.ActivityThread.main(ActivityThread.java:6709),位于com.android.internal.os.Zygote $ MethodAndArgsCaller.run(Zygote)的java.lang.reflect.Method.invoke(本机方法) .java:240),位于com.android.internal.os.ZygoteInit.main(ZygoteInit.java:769),我是我已经搜索了很多,却找不到答案。
如果我进行API调用,将应用程序置于后台,等待响应,并且在我返回到应用程序时,由于我试图立即显示对话框片段而导致应用程序崩溃,我也会遇到此错误(原因是我认为这是因为在显示对话框片段时,从后台返回时重新创建片段的事务仍在进行中。我通过设置对话框的500ms延迟来解决此问题,因为我找不到其他解决方案。
请询问您是否需要有关此的更多详细信息。先感谢您!
可能的温度解决方案
编辑
我通过将应用程序兼容性降低到了androidx.appcompat:appcompat:1.0.2这个级别来解决了这个问题,但这只是一个临时解决方案,因为我将来必须对其进行更新。我希望有人能解决。
编辑2 我通过从片段事务中删除setTransition()解决了该问题。至少我知道android应用总体上没有良好过渡的原因
编辑3 也许是避免此问题并让事情顺利进行的最佳解决方案,只是使用ViewPager处理底部栏导航
我有3个片段A,B,CI写了一段代码来替换它们并维护backstack:
public void addFragment(Fragment fragmentToAdd, String fragmentTag) {
FragmentManager supportFragmentManager = getSupportFragmentManager();
Fragment activeFragment = getActiveFragment();
FragmentTransaction fragmentTransaction = supportFragmentManager
.beginTransaction();
if (null != activeFragment) {
fragmentTransaction.hide(activeFragment);
}
fragmentTransaction.replace(R.id.layout_child_activity, fragmentToAdd,
fragmentTag);
if (supportFragmentManager.getBackStackEntryCount() > 1) {
supportFragmentManager.popBackStack();
}
fragmentTransaction.addToBackStack(fragmentTag);
fragmentTransaction.commit();
}
Run Code Online (Sandbox Code Playgroud)
在这段代码中
if (supportFragmentManager.getBackStackEntryCount() > 1) {
supportFragmentManager.popBackStack();
}
Run Code Online (Sandbox Code Playgroud)
如果堆栈长度大于1,我使用pop来获取最新的片段.现在由于这个,当长度大于1时,它会一次又一次地调用onCreate视图.喜欢 :
为什么我会遇到这种行为?当我删除斜体代码时,它没有发生.
android fragment android-fragments back-stack fragmentmanager
假设我们有两个活动.
A - 主要活动,即"启用主启动器"(适当的意图过滤器等)
B - 具有singleTask规范的任务根活动(此活动只能有一个实例)和自定义taskAffinity(用于区分主要任务)根).
假设B代表一个任务,只有当它没有完成时才有效 - 返回它或者在完成它之后从最近的任务再次启动它不是一个选项.
在某些时候 - A开始B开始新任务.目标是在用户完成B时从最近的任务列表中删除B.用户可以从B导航到其他任务(使用主页长按)然后导航回B,只要它没有完成.从启动器启动A不会将B带到前台,因为它们具有不同的任务关联性.
Android将B识别为任务的根,因此即使B已完成,B也会在最近的任务列表中可见,并且用户始终可以返回到该任务.使用A将B移动到一个任务不是解决方案,因为在B运行的时间 - 用户应该能够在A和B任务之间切换.将excludeFromRecents添加到B的清单会将其从最近的任务列表中完全删除,这也是不好的解决方案.
怎么实现呢?(对不起,我的英语不好)
我有两个片段Frag A和Frag B,它们使用view pager呈现.如果用户从A滑动到B然后按下后退按钮(在B中),则用户应该转到A而不是离开视图寻呼机.我们怎样才能做到这一点?
向Backstack添加事务似乎没有帮助.
谢谢
我有一个活动,包含片段'list',点击其中一个项目后会将其自身替换为'content'片段.当用户使用后退按钮时,他再次被带到"列表"片段.
问题是片段处于默认状态,无论我尝试持久化数据.
事实:
public static TheFragment newInstance(Bundle args),setArguments(args)并Bundle args = getArguments()FrameLayout父活动的内部(即不是嵌套片段)setRetainInstance,因为我的活动是主/细节流程,在大屏幕上有2个窗格布局.7"平板电脑有1个纵向画面和2个横向画面.如果我保留'list'片段实例,它会(我认为)搞乱屏幕旋转FragmentTransaction#replace(int, Fragment, String)以相同的ID但不同的标签显示onSaveInstanceState(Bundle),但是这并不总是被框架调用,正如文档所述:"在很多情况下,片段可能会被大部分拆除(例如放置在没有UI显示的后台堆栈上),但是它的状态在其拥有的活动实际上需要保存其状态之前不会被保存."从上面的子弹5中,我猜测片段事务后需要恢复内存的低端设备可能会调用Fragment#onSaveInstanceState(Bundle).但是,在我的测试设备(Galaxy Nexus和Nexus 7)上,框架不会调用该方法.所以这不是一个有效的选择.
那么,我如何保留一些片段数据呢?传递给捆绑Fragment#onCreate,Fragment#onActivityCreated等始终null.
因此,我无法从全新的片段启动到后台堆栈恢复有所作为.
注意:可能的相关/重复问题
我正在处理的应用程序的用户遇到了崩溃问题.这是我从控制台获得的堆栈跟踪.
java.lang.NullPointerException: Attempt to write to field 'int android.support.v4.app.Fragment.mNextAnim' on a null object reference
at android.support.v4.app.BackStackRecord.popFromBackStack(BackStackRecord.java:924)
at android.support.v4.app.FragmentManagerImpl.popBackStackState(FragmentManager.java:1605)
at android.support.v4.app.FragmentManagerImpl$4.run(FragmentManager.java:532)
at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1501)
at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:458)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:145)
at android.app.ActivityThread.main(ActivityThread.java:5942)
at java.lang.reflect.Method.invoke(Native Method)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1399)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1194)
Run Code Online (Sandbox Code Playgroud)
崩溃只发生在拥有5.x的Galaxy Note3或Galaxy S4手机的用户或者至少是我们唯一已经报告但已经发生了很多的手机.它似乎发生在片段之间的过渡或有时从相机返回时.这是我的过渡方法.
public void popBackStackToOr(String popBackFragmentName, String secondPopBackFragment)
{
int backStackId = 0;
int backStackCount = getSupportFragmentManager().getBackStackEntryCount();
List<Fragment> fragments = getSupportFragmentManager().getFragments();
for (int k = (backStackCount - 1); k > 0; k--)
{
String aFragmentClass = fragments.get(k).getClass().toString();
String[] …Run Code Online (Sandbox Code Playgroud)