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

时间:2013-10-24 07:57:52

标签: java android sqlite security ondestroy

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

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

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

所以我的问题;

  1. 为什么在应用程序未完成时会破坏活动?
  2. 更重要的是:如何在应用关闭或失去焦点时运行我的CleanUp方法?

4 个答案:

答案 0 :(得分:8)

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

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

因此,要回答第二个问题,请阅读有关onDestroy()方法的文档中的说明:

  

注意:不要指望将此方法称为保存位置   data!例如,如果某个活动正在编辑内容中的数据   提供者,这些编辑应该在onPause()或   onSaveInstanceState(Bundle),不在这里。 通常这种方法   实现释放与线程相关的资源   活动,以便被破坏的活动不会留下这样的东西   当其余的应用程序仍在运行时。有   系统将简单地杀死活动的托管的情况   进程中没有调用此方法(或任何其他方法),所以它   不应该被用来做那些打算留下来的东西   过程消失后。

所以很明显,这是一个制作清理过程的好地方。因此,您可以使用onPause()onStop()方法之一。

onStop()在文档中描述如下:

  

当您不再对用户可见时调用。您接下来会收到onRestart()onDestroy()或任何内容,具体取决于以后的用户活动。

onPause()在文档中描述如下:

  

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

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

此外,正如您可以阅读的那样,在这里进行清理可能会使您的应用变慢,但无论如何在每次获得/放松焦点时清理和重新创建数据库都是一个非常繁重的过程......

要恢复:使用onPause()方法和onResume()中的初始化过程进行清理过程。 请注意,使用此类流程时,您的应用程序可能会非常慢。

希望这可以帮到你。

答案 1 :(得分:2)

在背面销毁活动是正常行为。来自Android developers site

  

在某些情况下,您的活动会因应用程序的正常行为而被销毁,例如当用户按下“返回”按钮时...

为了检测应用程序何时进入后台,没有简单的方法调用可以让你知道。但是这个previous question包含了一些很好的答案。

答案 2 :(得分:0)

你不能在应用程序的java部分执行此操作(调用函数)。 只在本土部分。

答案 3 :(得分:0)

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

首先创建此服务类:

 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();
    }
}

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

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

现在,只需在应用关闭之前在任何地方启动服务即可。

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