我有三项活动,我们称它们为“一”、“二”和“三”。从活动一开始,按下按钮即可启动活动二。从活动二开始,按下按钮即可启动活动三。
够简单的。
现在,活动三需要从应用程序访问一些数据(可能存在也可能不存在)。在 THREE 的 onResume() 方法中,会检查数据,如果数据不存在,则活动结束,如下所示:
@Override
protected void onResume() {
super.onResume();
/* ... get data from app ... */
if (data == null) {
Toast.makeText(this, "Data not found", Toast.LENGTH_SHORT).show();
finish();
return;
}
/* ... other logic ... */
}
When data == null
, THREE完成、销毁并返回到“二”。一切都很好。
现在,在 TWO 中,按后退按钮会在 TWO 上调用 finish()
,但 TWO 永远不会调用 onDestroy()
。用户可以很好地返回到 ONE,但是任何后续返回到 2 的意图都不起作用,并且不会引发任何错误。 TWO 处于已完成(并暂停)但从未被破坏的状态,因此无法恢复。
那么,为什么“三”在这种情况下很重要呢?如果我删除上面代码块中的 finish()
调用,并依赖于“自然”完成“三”(通过使用后退按钮),那么当用户返回“一”时,“二”已完成正确销毁。
好吧,这就是真正令人困惑的地方......
保留 finish()
调用,我可以通过直接从 ONE 启动 3 个来缓解挂起,然后“自然”完成它(后退按钮)。在三个被摧毁(第二次)后,两个按预期打开。
我读到的所有内容都表明我应该可以在活动的 onResume()
中调用 finish()
。但在这种情况下,它会使某些东西处于不良状态,并阻止我破坏调用活动。
有想法吗?还是我把你的脑子翻了个底朝天?
编辑:
进一步的探索发现了这个宝石...
围绕三个中的 finish()
调用,使用大约 500 毫秒的 postDelay()
处理程序将让两个按预期关闭。就像这样:
@Override
protected void onResume() {
super.onResume();
/* ... get data from app ... */
if (data == null) {
Toast.makeText(this, "Data not found", Toast.LENGTH_SHORT).show();
Handler h = new Handler();
h.postDelayed(new Runnable() {
@Override
public void run() {
finish();
}
}, 500);
return;
}
/* ... other logic ... */
}
不完全是我的修复想法......
I have three activities, let's call them ONE, TWO and THREE. From activity ONE, a button press starts activity TWO. From activity TWO, a button press starts activity THREE.
Simple enough.
Now, activity THREE requires a bit of data accessible from the application (which may or may not be there). In THREE's onResume()
method, a check is made for the data and the activity is finished if it doesn't exist, like so:
@Override
protected void onResume() {
super.onResume();
/* ... get data from app ... */
if (data == null) {
Toast.makeText(this, "Data not found", Toast.LENGTH_SHORT).show();
finish();
return;
}
/* ... other logic ... */
}
When data == null
, THREE finishes, destroys and returns to TWO. All is well.
Now in TWO, pressing the back button calls finish()
on TWO, but TWO never calls onDestroy()
. The user is returned to ONE just fine, but any subsequent intent to go back to TWO does not work and no errors are thrown. TWO is left in a state where it has been finished (and paused), but never destroyed, and as a result cannot resume.
So, why is THREE important in this case? If I remove the finish()
call in the code block above, and rely on a "natural" finishing of THREE (by using the back button), when the user gets back to ONE, TWO has been destroyed correctly.
OK here's where it gets really confusing...
Leaving the finish()
call in place, I can alleviate the hangup by launching THREE directly from ONE, then "naturally" finish it (back button). After THREE is destroyed (a second time), TWO opens as expected.
Everything I've read has said I should be ok calling finish()
within onResume()
for an activity. But in this case, it is leaving something in a bad state and prevents me from destroying the calling activity down the line.
Ideas? or did I turn your brains inside out?
EDIT:
Further exploration uncovered this gem...
Surrounding the finish()
call in THREE with a postDelay()
handler of around 500 millis will allow TWO to close as expected. Like this:
@Override
protected void onResume() {
super.onResume();
/* ... get data from app ... */
if (data == null) {
Toast.makeText(this, "Data not found", Toast.LENGTH_SHORT).show();
Handler h = new Handler();
h.postDelayed(new Runnable() {
@Override
public void run() {
finish();
}
}, 500);
return;
}
/* ... other logic ... */
}
Not exactly my idea of a fix...
发布评论
评论(3)
按下后退时活动未完成/销毁。
使用
an activity is not finished / destroyed on back pressed.
Use
由于我无法发表评论,所以我会写在这里。
我不是 100% 确定我是否关注了你,但在接近尾声时你提到了这一点
你这是什么意思,因为如果我没听错的话,你说你用“一”中的按钮打开“二”,用“二”中的按钮打开“三”。那么 TWO 如何按预期打开,或者你的意思是当你退出它时它会转到 onDestroy() ?
我的目标是,也许您打开同一活动的更多实例,如 这里(如果您查看图 3)。
Since I can not comment I will write here.
I am not 100% sure if I followed you but right near the end you mention that
What do you mean by that since if I followed you correctly you said that you open TWO with a button in ONE and THREE with a button in TWO. So how can TWO open as expected, or you mean then it goes to onDestroy() when you exit it?
What I am aiming at is that perhaps you open more instances of the same activity, as is mentioned in the here if you take a look at Figure 3.
由于此问题仅在 onResume() 中发生[请参阅评论],我认为这听起来像是状态持久性的问题,而不是修补堆栈的问题。
看看这个 Stack Over Flow 问题 使用 Save Instance 保存 Android Activity 状态State
如果 onPause() 你将“数据”(我不知道它的对象类型,因为你没有说过)保存到 Bundle 然后 onResume() 去获取它。
Google 在此处找到的另一个示例,使用SharedPreferences 而不是 Bundle 来实现相同的结果。
总的来说,这意味着您可以处理/防止“数据”为空,因为您可以恢复它,因此节省了销毁三个数据并尝试摆弄堆栈的工作,只需用您的术语来保持工作流程“自然”即可。
Since this issue occurs only from onResume() [see comments] I would argue it sounds like an issue with state persistence rather than tinkering with the stack.
Take a look at this Stack Over Flow Question Saving Android Activity state using Save Instance State
If onPause() you save "data" (I do not know its object type as you have not said) into a Bundle then onResume() go get it.
Another example found here by Google, uses SharedPreferences instead of a Bundle to achieve the same result.
Overall this will mean you can handle/prevent "data" being null as you can restore it therefore saving the effort of destroying THREE and trying to fiddle with the stack, simply put in your terms keeping the workflow "natural".