1

我在我们的应用程序中使用 v4 支持库,并且我在应用程序中有一个基于步骤的过程,在正常情况下可以正常工作。但是,我们有一个要求,即一切都需要在内存压力情况下正常工作并且不会崩溃。所以我使用 SetAlwaysFinish 库来帮助解决这个问题(https://github.com/bricolsoftconsulting/SetAlwaysFinish)。它在确定需要检测和处理此类情况的区域方面非常有帮助,但我遇到了一个让我难过的问题。请记住,这在正常情况下可以正常工作,但我正在使用“setAlwaysFinish”= ON 进行明确测试。

这是我的设置:我有一个托管 ViewPager 布局的“ProcessActivity”类。ViewPager 有一个适配器集,其中包含我将包含该过程的片段列表。这是在 onCreate() 方法中:

进程活动

createSteps();  // this creates/populates the ArrayList "processSteps" with Fragments
theAdapter = new ProcessAdapter(this, processSteps); // the ProcessAdapter class extends FragmentStatePagerAdapter, with an additional list of Fragment steps
theViewPager.setAdapter(theAdapter);

还有其他部分,但这是其设置方式的核心。在其中一个片段步骤中,我实际上需要从步骤过程中“中断”并暂时推出一个活动以执行一些逻辑(然后返回到步骤过程)。我使用 ForResult 如下执行此操作,因为我需要能够在活动完成时处理活动中的 OK/Cancel 操作:

Step4片段

Intent intent = new Intent(getActivity(), ThePushActivity.class);
intent.putExtra(blah..);
startActivityForResult(intent, THE_REQCODE);

一旦它被推到这个视图上,有时 ProcessActivity 和 Step4Fragment 的 onDestroy() 方法都会被调用(由于 alwaysFinish)。有时它似乎工作正常,它会回调到 Step-Fragment 过程。但通常情况下,它会调用 ProcessActivity 的 onDestroy() 方法,然后在填充了 bundle saved-instance-state 的情况下重新调用 onCreate() 方法。这将调用上面的步骤创建代码,它将应用程序置于一个时髦的状态,用户正在执行的最后一步正在显示,但在幕后它实际上是第一步(此时,片段不在重击和断开连接),不可避免地会发生崩溃。在这一点上,Step4Fragment 似乎完全脱节,如果你尝试做任何事情,它会在某个地方崩溃,

关于解决这个问题的最佳方法有什么想法吗?我认为如果我能找到一种方法甚至只是重置一些东西,以便在发生内存问题时让用户回到流程的第一步,那很好。但是,当然,我最关心的是崩溃。

如果我需要提供更多细节,请告诉我。提前感谢您的帮助!

更新#1: 只是一个快速更新,我注意到片段被重新实例化和初始化,它正确地落入“当前”片段的 onActivityResult() 方法并正确执行它需要执行的操作。在这些场景之一之后,断开连接的位置似乎在基本 ProcessActivity 类中。ViewPager 布局正确显示,但 ViewPager 之外的所有内容都不正确(即它表明它处于流程的第 1 步,当它应该表明它处于第 4 步时,并且导航按钮显示为第 1 步而不是第四个)。

所以我猜我需要以某种方式手动正确设置这些元素。在深入研究这一点时,我可能会遗漏一些人需要积极帮助解决此问题的代码。如果我能以某种方式访问​​ ViewPager 字段的状态,该字段包含获取“当前显示的片段”的能力,在整个 onDestroy()/onCreate() 被调用之前,可能来自 savedInstanceState 包?那可能会解决我的问题。但是在调试时检查这个包,我几乎只能看到片段本身,以及它们各自的状态。不过,我会继续挖掘。

无论如何,请让我知道是否有人对如何正确完成此类事情有任何想法(当然是高水平的)。

更新#2 我看到即使“当前”片段似乎已正确启动,并且视图显示正确,一切都已分离。我无法在 getResources() 或 getActivity() 等上调用任何方法。实际上,我能够通过将步骤索引 (int) 保存到 savedInstanceState 包中,然后重新加载 UI,从而使 ProcessActivity“正常工作”周围的元素。但是,我仍然有这个阻止程序,当前 Fragment 与 Activity 分离,即使它似乎已正确重新实例化。

更新#3 当我按照这篇文章的方向进行操作时:ViewPager 和片段——存储片段状态的正确方法是什么?,当我尝试执行第一个 putFragment() 时,我立即出现异常。例外是:“IllegalStateException:Fragment Step4Fragment 当前不在 FragmentManager 中”。我认为这可能与我在任何时候只将一个片段保留在左侧和一个片段保留在右侧“活动”的事实有关(即 offScreenPageLimit)。

4

2 回答 2

0

事实证明,这个问题的解决方案类似于这篇文章中提出的解决方案:ViewPager 和片段——存储片段状态的正确方法是什么?

我有几件事需要改变。首先,我需要将片段移动到字段而不是临时变量。其次,我需要避免每次在 onCreate() 中实例化新的 Fragments。相反,它应该尝试将它们从 savedInstanceState 中拉出来,如下所示:

fragment1 = (Fragment1Step) getSupportFragmentManager().getFragment(savedInstanceState, Fragment1Step.class.getName());
fragment2 = (Fragment2Step) getSupportFragmentManager().getFragment(savedInstanceState, Fragment2Step.class.getName());
etc...

然后就在这之后,我对它们中的每一个进行了后续检查;如果它们是空的(即新的而不是来自保存的实例),那么它们将被实例化为新的:

if (fragment1 == null) {
    fragment1 = new Fragment1Step();
} 
if (fragment2 == null) {
    fragment2 = new Fragment2Step();
} 

当然,为了让它工作,这些也应该保存在 onSaveInstanceState() 方法中:

try {
    getSupportFragmentManager().putFragment(outState, Fragment1Step.class.getName(), fragment1);
} catch (Exception e) {
    // do nothing
}
try {
    getSupportFragmentManager().putFragment(outState, Fragment2Step.class.getName(), fragment2);
} catch (Exception e) {
    // do nothing
}
etc...

我在 try/catch 块中有这些的原因是因为我们的 ViewPager 只有一个 offScreenPageLimit 为 1,所以如果它们当前不在 Fragments 的“活动”堆栈中,其中一些将在“putFragment()”调用时抛出异常正在显示。

它不是非常漂亮,并且可能有更好的方法来处理这个..但是现在这似乎可以正常工作。

于 2013-05-22T22:05:17.740 回答
0

你确定你的 Fragment 没有被重新实例化吗?

Fragment 的所有子类都必须包含一个公共的空构造函数。框架通常会在需要时重新实例化一个片段类,特别是在状态恢复期间,并且需要能够找到这个构造函数来实例化它。如果空构造函数不可用,在状态恢复过程中某些情况下会出现运行时异常。

于 2013-05-20T22:40:58.777 回答