在应用程序/任务级别获取类似于onPause和onResume的事件

10
我想知道一个应用程序进入后台和返回前台时,为什么没有回调函数在应用程序级别上被调用。只有当前顶部的Activity类的onPauseonResume方法被调用。如果我想停止一些具有应用程序级别作用域的后台任务,那么当应用程序进入后台时就没有简单的方法可以停止它。这些事件回调有很高的需求。 为什么Android没有应用程序级别的暂停和恢复回调?如果不能在应用程序级别实现,是否可以在任务(activity堆栈)级别实现? 真正的问题是: 一个后台的Timertask定期从Web获取数据并刷新UI。当应用程序不再在前台时,我想停止它。 目前,我将重复的代码放在BaseActivity中,这是在activity级别上操作的。每个活动的暂停和恢复都会停止和启动任务,并且应用程序进入后台或返回前台的事件被隐藏在其中之一,我无法知道。我想知道是否有更好的方法来解决这个问题,也就是如何知道应用程序何时停止对用户可见。

1
这只是个猜测,所以我不会将其列为答案,但我认为这与Android的设计有很大关系。它被设计成从一个Activity到另一个Activity,而应用程序类本身仅被视为严格的全局状态设置,包括相关活动。然而,这些活动应该被设计为独立的,以便它们在需要时可以从其他应用程序中使用。 - DeeV
但是如果在应用程序级别无法进行回调,则可以在任务级别进行回调。 - Ron
3个回答

阿里云服务器只需要99元/年,新老用户同享,点击查看详情
4
请使用Handler而不是TimerTask。如果一个与Activity的Looper绑定的Handler没有被激活,那么定时消息将不会被触发。 模式是向Handler发送定时消息,然后再生成一个Thread/AsyncTask,在后台执行请求并更新UI。线程创建/销毁方面有些额外开销,但这是I/O绑定的。如果这个开销成为瓶颈,可以建立线程池(虽然我认为不太可能)。 如果你真的想知道你的应用何时不再在前台,可以使用两个活动之间onStop/onResume的重叠。从A到B时,B的onResume将在A的onStop之前调用。因此,你可以在onResume中递增一个全局计数器,在onStop中递减它。只有当没有活动可见时,该计数器才会变为0。我成功地使用这种方法来跟踪精确的访问量以进行分析。但这需要所有活动的一个共同的基类。

我希望任务在整个应用程序中运行,而不仅仅是一个活动的生命周期。 - Ron
从A到B的过程中,在调用B的onResume之前会先调用A的onStop。因此,在Activity A的onStop方法中,我应该检查计数器是否为零并停止任务。但这并不是正确的方式。 - Ron
这就是大致的想法。在我的情况下,我不得不为所有活动派生一个基类。此外,我还有一个单例对象ActivityVisibilityManager,它具有公共静态同步方法incrementCount、decrementCount和isVisible。在基类中,我只是调用了这些方法。 - Delyan
可以在Application对象中计数。无论如何,从性能上讲,这仍然是比我正在使用的更好的解决方案。+50。希望将来我们能够从Android获得回调,以处理此类事件。 - Ron
如果屏幕旋转,这个方法就不起作用了。这些调用没有重叠。 - ViliusK

3
您是指android.app.Application类吗?当您的应用程序启动时,在启动某个Activity或Service之前会创建一个单独的Application,它的生命周期与您的应用程序在内存中保持一致。 您可以扩展此Application并在manifest文件中指定扩展类的名称,例如:<application android:name=".YourApp">。 现在您应该明白,Application本身不会进入前台或后台,只有Activity才能。然而,从Activity中,您可以调用getApplication以获取单个Application实例(使用强制类型转换),并调用与焦点更改相关的自己的方法,从而知道您的整个应用程序是在前台还是后台,并根据需要进行操作。 Service也有一个getApplication()方法,它接收相同的Application对象。 大多数开发人员可能没有意识到,他们可以拥有单个Application对象来保留所需的应用程序数据,而不仅仅是一堆Activities和Services。

这基本上是我现在处理的方式。我将重复的代码放在BaseActivity中。这是在活动级别上。每个活动的暂停和恢复以及应用程序进入后台或返回前台的事件都会导致任务停止和启动,其中一个事件发生在这些事件之一上,我无法知道。我想知道是否有更好的方法来做到这一点,我的意思是知道应用程序何时不再对用户可见。 - Ron
当应用程序的任何活动进入后台(调用onPause)时,该应用程序停止对用户可见。 - Pointer Null
调用 onPause 意味着您的活动将进入后台,但并不总是意味着应用程序将进入后台。即使启动了新活动,当前活动的 onPause 也会被调用,这并不意味着您的应用程序已经进入后台。您在回答中的观点 - “应用程序本身不会进入前台或后台,只有活动可以” 我需要知道何时应用程序进入后台,例如当按下主页按钮或通过点击通知启动新应用程序时。 - Ron
尝试使用Activity.onUserLeaveHint。 - Pointer Null

0
如果您想执行一些具有应用程序级别范围的后台任务,则应在服务上启动一个新线程来为您执行此任务。 服务与任何活动无关,因此将继续运行您的任务线程,直到您停止它。

1
是的,目前解决他的问题的一种方法是创建一个服务,然后使用各个活动的onPause()和onResume()来跟踪您的应用程序何时在前台,然后在不在时停止服务()。但我认为他的问题是为什么需要这么多样板代码才能使这个相当常见的模式工作。 - Joel F
@Joel F:是的,完全正确。我可以在没有服务的情况下停止和启动任务,但必须在应用程序中每个活动的onPauseonResume上执行相同的操作。 - Ron
我现在明白你的意思了。你想要在应用程序不再处于前台时停止任务?请问这个任务是什么类型的工作?它必须在应用程序不再处于前台时立即停止吗? - mcnicholls
它会定期从网络刷新UI数据。当应用程序不再处于前台时,我想停止它。 - Ron

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,