Android通过生命周期组件支持这一点。
2018年3月更新*现在有了更好的解决办法。看见ProcessLifecycleOwner..您将需要使用新的体系结构组件1.1.0(目前最晚),但它是特别是就是为了这么做的。
这里提供了一个简单的示例在这个答案中但我写了一个样本应用程序和一个博客帖子关于这件事。
自从我在2014年写了这篇文章以来,出现了不同的解决方案。有的起作用,有的起作用被认为是有效的,但也有缺点(包括我的!)作为一个社区(Android),我们学会了忍受后果,并为特殊情况编写了解决办法。
永远不要假设一个代码片段就是您想要的解决方案,这是不太可能的;更好的是,尝试理解它所做的事情以及它所做的事情。
这个MemoryBoss类从来没有像这里所写的那样被我实际使用,它只是一段碰巧起作用的伪代码。
除非有合理的理由不使用新的体系结构组件(而且有些组件,尤其是针对超级老API的组件),否则请继续使用它们。他们远非十全十美,但也不是十全十美。ComponentCallbacks2.
更新/说明(2015年11月)人们一直在发表两点意见,首先是>=应该使用而不是==因为文档表明不应该检查确切的值..这在大多数情况下都是可以的,但请记住,如果只关心做某物当应用程序转到后台时,您必须使用=和还可以将它与另一个解决方案(比如活动生命周期回调)结合起来,或者您可能不会你想要的效果。这个例子(发生在我身上)是,如果你想锁当你的应用程序有密码屏幕时,当它转到后台时(比如1 Password,如果你熟悉它),如果你内存不足,突然开始测试,你可能会意外地锁定你的应用程序。>= TRIM_MEMORY,因为Android将触发LOW MEMORY打电话比你的高。所以,要小心你测试的方法/内容。
此外,一些人还问到如何检测你什么时候回来。
我能想到的最简单的方法是在下面解释,但是由于有些人不熟悉它,所以我在这里添加了一些伪代码。假设你有YourApplication而MemoryBoss课程,在您的class BaseActivity extends Activity(如果没有,则需要创建一个)。@Overrideprotected void onStart() {
super.onStart();
if (mApplication.wasInBackground()) {
// HERE YOU CALL THE CODE YOU WANT TO HAPPEN ONLY ONCE WHEN YOUR APP WAS RESUMED FROM BACKGROUND
mApplication.setWasInBackground(false);
}}
我推荐开始,因为对话框可以暂停一个活动,所以我敢打赌,如果你所做的只是显示一个全屏对话框,你肯定不希望你的应用程序认为“它进入了背景”,但是你的里程可能会有所不同。
仅此而已。if块中的代码将只执行一次,即使你去参加另一项活动,新的活动(那也是extends BaseActivity)将报告wasInBackground是false所以它不会执行代码,直到onMemoryTrimmed将调用该标志,并再次将该标志设置为true。.
希望能帮上忙。
更新/说明(2015年4月):在您对此代码进行所有复制和粘贴之前,请注意,我已经发现了一些情况,其中一些情况可能不是100%可靠的,而且必须合并用其他方法达到最佳效果。值得注意的是两个已知实例在那里onTrimMemory不能保证执行回拨:如果你的手机在你的应用程序可见时锁定屏幕(比如你的设备在nn分钟后锁定),这个回调就不会被调用(或者不总是),因为锁屏就在顶部,但是你的应用程序仍然在“运行”,尽管覆盖了。
如果您的设备内存相对较低(以及在内存紧张的情况下),操作系统似乎会忽略此调用,直接进入更关键的级别。
现在,根据您了解应用程序何时进入后台的重要性,您可能需要或不需要扩展此解决方案,同时跟踪活动生命周期以及诸如此类的内容。
只需牢记以上所述,并有一个优秀的QA团队;)
更新结束
可能已经晚了,但是有一个可靠的方法冰淇淋三明治(空气污染指数14及以上).
结果发现,当应用程序没有更可见的UI时,就会触发回调。可以在自定义类中实现的回调名为ComponentCallbacks 2(是的,有两个)。这个回调是只提供在空气污染指数第14级(冰淇淋三明治)及以上。
基本上,您可以调用该方法:public abstract void onTrimMemory (int level)
级别为20或更具体public static final int TRIM_MEMORY_UI_HIDDEN
我一直在测试这一点,而且它总是有效的,因为20级只是一个“建议”,您可能想发布一些资源,因为您的应用程序是不可见的。
引用官方文件:onTrimMemory(Int)级别:该流程显示了用户界面,并且不再这样做。此时应该释放UI的大量分配,以便更好地管理内存。
当然,你应该按照它说的来实现它(清除某些时间没有使用的内存,清除一些未使用的集合,等等)。这些可能性是无穷无尽的(其他可能见官方文档)。更具批判性级别)。
但是,有趣的是,操作系统告诉你:嘿,你的应用程序到后台去了!
这正是你一开始想知道的。
你怎么确定你什么时候回来的?
很简单,我肯定你有“基本能动性”所以你能,会,可以使用onResume()标记返回的事实。因为你唯一会说你不回来的时候,你真的接到了上面的电话onTrimMemory方法。
它起作用了。你不会得到假阳性的。如果一项活动正在恢复,你就会回来,100%的时间。如果用户再次返回后台,您将得到另一个onTrimMemory()打电话。
您需要约束您的活动(或者更好地说,是一个自定义类)。
确保始终收到此消息的最简单方法是创建这样一个简单的类:public class MemoryBoss implements ComponentCallbacks2 {
@Override
public void onConfigurationChanged(final Configuration newConfig) {
}
@Override
public void onLowMemory() {
}
@Override
public void onTrimMemory(final int level) {
if (level == ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN) {
// We're in the Background
}
// you might as well implement some memory cleanup here and be a nice Android dev.
}}
为了使用这一点,在应用程序实现中(你有一个,对吧?),做如下事情:MemoryBoss mMemoryBoss;@Overridepublic void onCreate() {
super.onCreate();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
mMemoryBoss = new MemoryBoss();
registerComponentCallbacks(mMemoryBoss);
} }
如果创建一个Interface您可以添加一个else对此if和实施ComponentCallbacks(没有在API 14下面的任何内容中使用的2)。onLowMemory()方法和当您进入后台时,不会被调用。但你应该用它来修剪记忆。
现在启动你的应用程序并按主页。你的onTrimMemory(final int level)方法应该被调用(提示:添加日志记录)。
最后一步是从回调中取消注册。也许最好的地方是onTerminate()你的应用程序的方法,但,该方法不会在真正的设备上调用:/**
* This method is for use in emulated process environments. It will
* never be called on a production Android device, where processes are
* removed by simply killing them; no user code (including this callback)
* is executed when doing so.
*/
因此,除非您真的不想被注册,否则您可以安全地忽略它,因为您的进程在OS级别上已经濒临死亡。
如果您决定在某个时候取消注册(例如,为您的应用程序提供一个关闭机制来清理和销毁),您可以这样做:unregisterComponentCallbacks(mMemoryBoss);
仅此而已。