Java Android 应用程序关闭或失去焦点时如何调用方法?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19560171/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-12 18:20:07  来源:igfitidea点击:

How to call a method when an Android app is closed or loses focus?

javaandroidsqlitesecurityondestroy

提问by kramer65

Because an app I'm building will handle rather sensitive data I want to sync the SQLite db with the server every time the user logs in, and remove emty the db every time the app loses focus (because the user moves to the home screen or another app).

因为我正在构建的应用程序将处理相当敏感的数据,所以我想在每次用户登录时将 SQLite 数据库与服务器同步,并在每次应用程序失去焦点时删除数据库(因为用户移动到主屏幕或另一个应用程序)。

Seeing the Activity lifecycle, my idea was to do this by emptying the database in the onDestroy of every Activity. To test the described lifecycle I just Override all lifecycle methods (onCreate, onStart, onResume, onPause, onStop, and onDestroy), included some log messages in them, and fired up my app.

看到Activity 生命周期,我的想法是通过清空每个 Activity 的 onDestroy 中的数据库来做到这一点。为了测试所描述的生命周期,我只是覆盖了所有生命周期方法(onCreate、onStart、onResume、onPause、onStop 和 onDestroy),在其中包含了一些日志消息,并启动了我的应用程序。

The log messages are included in my SettingsActivity. When I enter my app and move to the Settings it runs onCreate, onStart and onResume (as expected). When I then click a setting and move to the next screen it runs onPause and onStop (still as expected). To move back to the settings screen I click the back button and it runs onStart and onResume again (still as expected), when I now click the back button again to move back to the initial screen, it (to my surprise) runs onPause, onStop AND onDestroy.

日志消息包含在我的 SettingsActivity 中。当我进入我的应用程序并移动到设置时,它会运行 onCreate、onStart 和 onResume(如预期的那样)。当我然后单击一个设置并移动到下一个屏幕时,它会运行 onPause 和 onStop(仍然如预期的那样)。要返回设置屏幕,我单击后退按钮,它再次运行 onStart 和 onResume(仍然如预期的那样),当我现在再次单击后退按钮返回初始屏幕时,它(令我惊讶的是)运行 onPause, onStop 和 onDestroy。

So my questions;

所以我的问题;

  1. Why does it destroy the Activity when the app is not finished?
  2. And more importantly: how can I run my CleanUp method when the app closes or loses focus?
  1. 为什么在应用程序未完成时它会销毁 Activity?
  2. 更重要的是:当应用程序关闭或失去焦点时,我如何运行我的 CleanUp 方法?

采纳答案by mithrop

You can have some more information here : http://developer.android.com/training/basics/activity-lifecycle/stopping.html

您可以在此处获得更多信息:http: //developer.android.com/training/basics/activity-lifecycle/stopping.html

Even if I think you already read it because you already study the activity lifecycle, you can see in the first figure that the onDestroy()is called after the onStop()and this call is totally managed by the system : you shouldn't expect any behavior. The system will decide itself WHEN to call this method, and sometimes, this method will never be called (see here : http://developer.android.com/reference/android/app/Activity.html). When system needs memory, your activity will pass in onStop()and nothing more.

即使我认为您已经阅读了它,因为您已经研究了 Activity 生命周期,您可以在第一个图中看到在onDestroy()之后onStop()调用 并且此调用完全由系统管理:您不应该期望任何行为。系统将自行决定何时调用此方法,有时永远不会调用此方法(请参阅此处:http: //developer.android.com/reference/android/app/Activity.html)。当系统需要内存时,您的活动将传入onStop(),仅此而已。

So, to answer your second question, you shloud read the note in the documentation about the onDestroy()method :

因此,要回答您的第二个问题,您应该阅读有关该onDestroy()方法的文档中的注释:

Note: do not count on this method being called as a place for saving data!For example, if an activity is editing data in a content provider, those edits should be committed in either onPause() or onSaveInstanceState(Bundle), not here. This method is usually implemented to free resources like threadsthat are associated with an activity, so that a destroyed activity does not leave such things around while the rest of its application is still running. There are situations where the system will simply kill the activity's hosting process without calling this method (or any others) in it, so it should not be used to do things that are intended to remain around after the process goes away.

注意:不要指望这个方法被调用作为保存数据的地方!例如,如果活动正在内容提供者中编辑数据,则这些编辑应在 onPause() 或 onSaveInstanceState(Bundle) 中提交,而不是在此处提交。此方法通常用于释放与活动相关联的线程等资源,以便被销毁的活动不会在其应用程序的其余部分仍在运行时留下这些东西。在某些情况下,系统将简单地终止活动的托管进程,而不会在其中调用此方法(或任何其他方法),因此不应使用它来执行在进程消失后打算保留的事情。

So it's pretty clear that it's a bad place to make your clean-up process. So you shloud use one of onPause()or onStop()method.

所以很明显,这是一个进行清理过程的坏地方。所以你应该使用其中之一onPause()onStop()方法。

onStop()is described like this in the documentation :

onStop()在文档中是这样描述的:

Called when you are no longer visible to the user. You will next receive either onRestart(), onDestroy(), or nothing, depending on later user activity.

当您不再对用户可见时调用。接下来,您将收到要么onRestart()onDestroy()或什么都没有,这取决于后来的用户活动。

onPause()is described like this in the documentation :

onPause()在文档中是这样描述的:

Called as part of the activity lifecycle when an activity is going into the background, but has not (yet) been killed. [...] When activity B is launched in front of activity A, this callback will be invoked on A. B will not be created until A's onPause() returns, so be sure to not do anything lengthy here.[...] In situations where the system needs more memory it may kill paused processes to reclaim resources.

当活动进入后台但尚未(尚未)被终止时,作为活动生命周期的一部分被调用。[...] 当活动 B 在活动 A 之前启动时,将在 A 上调用此回调。在 A 的 onPause() 返回之前不会创建 B,因此请确保不要在这里做任何冗长的事情。[...] 在系统需要更多内存的情况下,它可能会杀死暂停的进程以回收资源。

We now know that onPause()is designed to allow you to save your data, and also that after onPause()was executed, the system couldkill your process. So, making the clean-up in onPause()seems to be the safest place as you're pretty sure it will be called everytime.

我们现在知道它onPause()旨在允许您保存数据,并且在onPause()执行后,系统可能会终止您的进程。因此,在 in 中进行清理onPause()似乎是最安全的地方,因为您很确定每次都会调用它。

Also, as you can read, making your clean up here can make your app slow, but anyway cleaning and recreating your database at each gain/loose of focus is a really heavy process...

此外,正如您所读到的,在此处进行清理会使您的应用程序变慢,但是无论如何,在每次获得/失去焦点时清理和重新创建数据库是一个非常繁重的过程......

To resume : make your clean up process in the onPause()method and your init process in the onResume(). Keep it mind that your application can be really slow with this kind of process.

恢复:在onPause()方法中进行清理过程,在onResume(). 请记住,使用这种过程,您的应用程序可能会非常缓慢。

Hope this can help you.

希望这可以帮到你。

回答by theWalker

You can't do this (call a function) in java part of app. Only in the native part.

您不能在应用程序的 java 部分执行此操作(调用函数)。仅在本机部分。

回答by Francis

Destroying the Activity on back is the normal behavior. From the Android developers site

销毁背面的 Activity 是正常行为。来自Android 开发者网站

There are a few scenarios in which your activity is destroyed due to normal app behavior, such as when the user presses the Back button...

在某些情况下,您的 Activity 由于正常的应用行为而被破坏,例如当用户按下后退按钮时...

Has for detecting when the application goes to background, there is no simple method call that will let you know that. However this previous questioncontains some nice answers on how to do it.

用于检测应用程序何时进入后台,没有简单的方法调用可以让您知道这一点。然而,上一个问题包含一些关于如何做的很好的答案。

回答by danielrosero

About your second question, this way you could run your CleanUp method when the app closes fully. You will need to implement your method inside a service that in this case I named "ExitService"

关于您的第二个问题,这样您就可以在应用程序完全关闭时运行 CleanUp 方法。您将需要在服务中实现您的方法,在这种情况下,我将其命名为“ExitService”

First create this service class:

首先创建这个服务类:

 public class ExitService extends Service {


    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onTaskRemoved(Intent rootIntent) {
        System.out.println("onTaskRemoved called");
        super.onTaskRemoved(rootIntent);
        //do something you want before app closes.

ADD YOUR METHOD HERE, or CALL IT

        //stop service
        this.stopSelf();
    }
}

Then, declare this way your service in the manifest "application" label:

然后,以这种方式在清单“应用程序”标签中声明您的服务:

<service
            android:enabled="true"
            android:name=".ExitService"
            android:exported="false"
            android:stopWithTask="false" />

Now, just start the service wherever you want to do something before your app closing.

现在,在您的应用程序关闭之前,只要您想在任何地方启动该服务即可。

 Intent intent = new Intent(this, ExitService.class);
        startService(intent);