据我了解,销毁的活动并不等同于已完成的活动。
finish()
),或者由用户按后退键(隐式调用finish()
)。所以如何完成销毁的活动? finish()
方法需要Activity
对象,但如果活动被销毁,我没有Activity
对象 - 我不应该持有对被破坏活动的引用,是吗?
案例研究:
我有一个a
活动,启动b
,然后启动c
(使用Activity.startActivity()
),现在back stack为:< / p>
a → b → c
在c
中,用户填写表单并点按“提交”按钮。使用AsyncTask
向远程服务器发出网络请求。任务完成后,我会显示toast并通过调用c.finish()
完成活动。完美。
现在考虑这种情况:
当异步任务正在进行时,用户切换到另一个应用程序。然后,由于内存限制,Android操作系统决定销毁所有3项活动(a
,b
,c
)。之后,异步任务完成。现在我该如何完成c
?
我尝试过的内容:
c.finish()
:
c
已被销毁。b.finishActivity()
:
b
已被销毁。将Context.startActivity()
与FLAG_ACTIVITY_CLEAR_TOP
一起使用,以便将b
提升到最高位置,从而完成c
:
// appContext is an application context, not an activity context (which I don't have)
Intent intent = new Intent(appContext, B.class); // B is b's class.
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
appContext.startActivity(intent);
appContext.startActivity()
抛出异常:android.util.AndroidRuntimeException:从Activity上下文外部调用startActivity()需要FLAG_ACTIVITY_NEW_TASK标志。这真的是你想要的吗?
编辑: 澄清:我需要等到异步任务完成,然后根据服务器确定是否完成c
响应。
答案 0 :(得分:2)
android.util.AndroidRuntimeException:从中调用startActivity() 在Activity上下文之外需要FLAG_ACTIVITY_NEW_TASK 旗。这真的是你想要的吗?
当您从中启动活动时,会发生此异常
后台线程或服务。你需要通过
只要您需要“发射器”,FLAG_ACTIVITY_NEW_TASK就会标记
行为类型。
mIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
即可避免此异常。现在,您可以做什么?
如果您在应用程序不在前台时遇到完成活动的问题,您可以做的是实施安全检查,只有当应用程序在前台进行后台堆栈活动时才会完成活动或否则就跳过这一步。
我认为你正试图在应用程序处于后台时终止活动。这样做似乎有点困难,但您可以使用onUserLeaveHint来确定应用程序何时在后台运行以完成活动,或者您可以通过添加finish();
来完成活动在onStop()
。只要确保asynctask的onPost()
没有按顺序再次完成它以避免异常。
查看android:clearTaskOnLaunch属性并将其设置为true。
Google Doc说这个属性是:
例如,有人从主屏幕启动活动P, 从那里开始活动Q.用户接下来按Home,然后 然后返回活动P.通常,用户会看到活动Q, 因为这是他们最后在P的任务中所做的事情。但是,如果P设定 这个标志为“true”,所有活动都在它之上(Q在此 当用户按下Home并且任务转到了 背景。因此用户在返回任务时只看到P.
我认为这是你想要的确切案例。
希望这会给你一些提示,以实现你想要的任务。
答案 1 :(得分:1)
您可以使用c中的onPostExecute
方法广播您的操作,并在a和b中注册广播receiver
以接收该操作。然后在接收器onRevice
方法
在c
,AsyncTask,
void onPostExecute(Long result) {
----
Intent intent1 = new Intent("you custom action");
context.sendBroadcast(intent1);
}
a
和b
registerReceiver(new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
finish();
}
},new IntentFilter("you custom action"));
答案 2 :(得分:1)
就个人而言,我会使用通知栏通知用户他的查询状态。
这样,我就可以避免完成一项未完成的活动。只有当用户还没有点击提交按钮时,我才会保持活动未完成。
答案 3 :(得分:0)
关于在活动被销毁之前调用的android manual onDestroy()
,所以你可以在其中调用finish(即使你可以在完全杀死活动之前停止你的bg线程)。
我们可以假设,如果活动被杀死,我们也不会对bg线程感兴趣,例如,如果bg线程要下载需要完成的图像或者等等 - 所以你必须使用服务而不是asynctask。< / p>
答案 4 :(得分:0)
无法直接完成已销毁的活动,因此只需finish()
onCreate()
(由@Labeeb P建议)。方法如下:
如果活动在尝试完成时已被销毁,请在某处保存一个布尔标记。
if(activity != null)
{
// Activity object still valid, so finish() now.
activity.finish();
}
else
{
// Activity is destroyed, so save a flag.
is_activity_pending_finish = true;
}
SharedPreferences
(由@Labeeb P建议)。在活动的onCreate()
中,检查标记并致电finish()
。
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
if(is_activity_pending_finish)
{
is_activity_pending_finish = false; // Clear the flag.
// This activity should have been finished, so finish it now.
finish();
return;
}
...
}
在finish()
中调用onCreate()
实际上是一项有效的操作,正如the doc中提到的那样:
...您可以从
finish()
内拨打onCreate()
来销毁活动。在这种情况下,系统会立即调用onDestroy()
而不调用任何其他生命周期方法。
其他考虑因素:
当然,被破坏的活动并不一定意味着应用程序处于后台(可能还有其他前台活动)。不过,上述解决方案(在finish()
中调用onCreate()
)仍可正常工作。
答案 5 :(得分:0)
当系统试图销毁您的活动时,它会调用onSaveInstanceState
。在这里,您可以致电finish()
。那就是它。
警告:我从未尝试过此操作,因此我不确定是否存在从onSaveInstanceState调用finish()的任何问题。如果你试试这个,请发表评论,让我知道它是如何运作的。