繁体   English   中英

最简单的 Android Activity 生命周期

[英]Simplest Android Activity Lifecycle

我注意到自从我启动我的应用程序以来,Android Developers Activity 部分已经更新,但我仍然不清楚最简单的 Activity Lifecycle 是什么。

据我所知:

onCreate、onResume 和 onPause 是必不可少的。

活动可能会在 onPause 之后的任何时间被删除,所以我应该将我的整个应用程序状态保存到一个文件 onPause 而不是依赖于 onStop 或 onDestroy。 此外,onSaveInstanceState 不会在每次 onPause 之前调用,因此并不值得使用。

与其尝试编写大量代码来处理所有场景,为什么不在 onPause 结束时销毁 Activity?

Lifecycle 将在处于活动状态之前 onCreate 和 onResume,然后在变为非活动状态时 onPause。 不需要其他方法。

我会使用 onCreate 来调用 setContentView 并设置视图侦听器,但其他所有内容都将放在 onResume 中,包括从文件加载恢复的状态? 如前所述,onPause 会将状态保存到文件并销毁活动。

据我所知,唯一的缺点可能是当屏幕上出现弹出窗口时,活动将被删除,并且必须在弹出窗口关闭时重新创建,这意味着该活动在弹出窗口后面不可见(尽管我没有测试过这个)

重新启动活动可能需要更长的时间,但由于系统可能会在没有任何通知的情况下删除活动,因此您无论如何都必须保存整个状态。

有什么想法吗?

更新:我想我在想的是“首页”活动在哪里调用游戏活动。 当玩家点击“播放”时,首页活动将调用游戏活动

游戏活动将在 onCreate 中设置其视图和侦听器等,并在 onResume 中加载包含游戏状态的文件,如果不存在文件,则启动新游戏。

onPause 游戏,它将游戏状态写入文件,然后无论游戏活动发生什么(什么都没有,或者被停止/破坏,或者其他) onResume 方法总是会再次从文件中重新加载所有数据。

这就是我的想法,如果这有意义吗?

更新 2:如果有人感兴趣,我已经设计了一个简单的解决方案,我已经记录在下面的答案中!

它不支持 Android Activity Lifecycle 'Paused' 和 'Stopped' 状态。 一旦它不再显示,它就会自行杀死并且必须手动重新启动,但它确实会从您停止的地方继续运行!

你在找这个吗?

活动生命周期

为了进一步回答您的问题,是的,您可以从上图中清楚地看出,“最简单”(即最少的方法调用次数)生命周期确实是onCreate(); onStart(); onResume(); onPause(); onCreate(); onStart(); onResume(); onPause(); .

您还应该了解onSaveInstanceState()onRetainNonConfigurationInstance() 这些不是生命周期方法。

所有这些方法都有很好的文档记录。 请仔细阅读本文档。

为了进一步澄清事情,这里有几个现实生活场景:

  1. 活动正在运行,其他活动在其之上, onPause被调用。 系统内存不足,调用onSaveInstanceState ,终止活动。 用户按下几次后,必须重新实例化活动(最好使用保存在onSaveInstanceState的数据)。
  2. 活动正在运行,用户按回。 此时onPause->onDestroy被调用,而不调用onSaveInstanceState

您应该了解onPauseonSaveInstanceState之间的本质区别。 前者总是被调用,而后者仅在活动实例将来可能被重新实例化时被调用。 按照这个思路,您的用户会期待两件事:

  1. 当他们离开您的 Activity 并稍后返回时,他们希望它与离开它的实例完全相同(这将使用onSaveInstanceState实现)。 如果他们退出您的活动,他们不会期望。 然而:
  2. 他们希望他们输入的数据将被持久化(这将在onPause完成)。 例如,如果他们开始撰写消息,他们希望在下次回来时将其视为草稿,即使他们退出了活动。

您应该明白这些方法应该如何才能被用来获取你的用户的期望。 您如何实际使用它们取决于您、您的需求和您的应用程序的性质。

Android 系统正在处理生命周期:即实例化活动和调用生命周期方法。 所以我不知道你所说的“破坏活动”是什么意思。 您作为开发人员,没有这种能力。

其次,活动生命周期流程有时会令人困惑(我知道我一开始就遇到了困难)。 因此,只需实现所有生命周期方法并将日志记录语句放入其中即可。 然后尝试所有实际用例(包括在应用程序使用期间接收调用)以查看生命周期方法是如何调用的。

我正在研究活动生命周期以及当您开始任何活动时所发生的完整过程,从onCreate开始。 这是一个 UML 图来帮助你。

单击此链接可查看高分辨率版本。

在此处输入图片说明

答案就像生命周期一样简单。 仅当您需要处理其中的内容时才覆盖回调。

除非在某些情况下,Android 将始终按照预期的方式调用每个回调。

仅仅因为某些回调不能保证被调用并不意味着它们是无用的。 只是不要尝试在此类回调方法中处理合理的内容。

我个人认为开发人员应该将工作划分为不同的活动状态。 在这种情况下,必须保留工作的顺序,我认为更重要的是,这就是为什么 Android 无法在单个线程中处理长时间的 UI 处理,并且它给出了错误,即 Android 有“太多工作要做”这个引用有时可能会导致崩溃 所以我们应该防止在一个部分中编写整个代码。 代码将被写入不同的函数或类,我们可以根据需要派生这些函数。 谢谢。

Android 应用中有 7 种管理活动生命周期的方法:

  1. 在创建()
  2. 开始()
  3. onResume()
  4. 重启()
  5. 暂停()
  6. 停止()
  7. 销毁()

我在我的博客上更深入地写了这些方法

根据@Felix 提供的答案,成熟的、功能齐全的、功能齐全的 Android 应用程序被转换(状态 = 时间函数)。

但是,如果您只想创建一个甚至没有 GUI 的应用程序呢? 你想要最简单的生命周期,那么我有下面的答案。

你可能会觉得这个答案很有趣。 Android 系统在阅读 AndroidManifest.xml 后知道哪个是入口点。 无论哪个活动都有这个

<activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

将是系统开始的起点或入口点。 在此之后,您的应用程序进程获得了可以自行启动的内存。

您的主要流程创建是Android系统的任务。 当一个应用程序组件启动并且该应用程序没有任何其他组件在运行时,Android 系统会启动一个新的 Linux 进程。 在进程调用onCreate() 之后,它创建主线程。 这就是您必须调用onCreate()的原因,因为主线程随后被初始化,主线程是您未来所有操作的触发器。

在 onCreate() 上,您获得了主线程。 在那之后,这完全取决于你,你想调用什么回调。 没有任何规则必须在 onCreate() 之后调用 onStart()。

只有一种生命周期方法 onCreate() 保证是您组件的生命周期返回。

此外,为了了解每个生命周期方法在其中做什么,请放置以下代码。

//add the log line
        Log.i(this.getClass().getCanonicalName(), "##############");
        int count = 0;
        for (StackTraceElement stackTraceElement:  Thread.currentThread().getStackTrace()) {
            count++;
            Log.i(this.getClass().getCanonicalName(), "\""+Thread.currentThread().getStackTrace()[2].getMethodName()+"\" "+count+" "+stackTraceElement.getMethodName());
        }; //end of log line

因此,始终添加上面相同的代码以在 log cat 控制台中查看日志。

当您的应用程序启动 GUI 时,它会调用 onStart()。 如果不在回调中调用 super() 方法, android 系统会显示管道损坏错误,并且无法进行进一步的处理和调试。

在此处输入图片说明

但是,您可以在每个回调方法中实现自己的逻辑。 例如,您可以在 onStart() 上对两个数字求和。

因此,所有 android 回调方法都是部分实现的方法。 它们不是纯粹的抽象方法,因为您应该在它们内部调用 super() 方法

附图说明:应用程序主进程调用onCreate(),它将其职责委托给主线程(UI线程),主线程调用其他16个回调。

在此处输入图片说明

此外,如果您想在特定时间查看所有方法,请将其放在代码下方。

//to see all the methods (including super methods) at this time, you call use the java reflection as below
    Log.i(this.getClass().getCanonicalName(), "##############");
    int count1 = 0;
    for (Method method:  this.getClass().getMethods()) {
        count1++;
        count++;
        Log.i(this.getClass().getCanonicalName(), count1+" "+method);
    }; //end of log line

    //At another time, after you add some other methods or android using GC removes some methods, you see your changed state (Bundle Snapshot) of your class
    //Because your bundle (i.e, the state of your class/activity) is the function of time.

在我的场景中,从上面的代码片段中,我看到它调用了 375 个方法。

注意:如果您在使用上面的代码片段打印所有方法之前在 onCreate() 中添加了另一个方法,您也会看到该方法。 这意味着,你的课堂状态(即快照)取决于你,你一次又一次地做什么,你不断更新你的快照。

onCreate() 显然首先。 然后您的活动可以进入 onPause()。 从那里它可以是 onResume() 或 onDestroy()。 这是我所知道的生命周期中最简单的路径。

我有一个没有 onPause() 方法的活动。 通过一系列奇怪的事件,我在 DDMS 中注意到我的应用程序不可见,但它仍在从 AdMob 请求 freshAds :) 不错的电池吸盘。 这已经解决了,但提醒我简单的事情是多么重要。

我想我已经找到了我要找的东西! (我 1,波诺 0)

这是针对单个“游戏”活动,它使用最少的方法来控制处理游戏的“游戏线程”线程。 它使用一个额外的“GameData”类来保存激活之间需要持久化的数据。

如果应用失去焦点(即来电,或用户点击返回等),Game 会将 GameData 保存到文件中并退出。 要继续,只需再次启动应用程序,它就会立即返回到您离开的地方。

布局文件'game.xml'是一个覆盖整个屏幕的SurfaceView

游戏.java:

  1. onCreate 为 SurfaceView 设置 SurfaceHolder 并创建 GameThread
  2. surfaceChanged调用GameThread.startThread启动GameThread,如果还没有启动,则传递屏幕尺寸
  3. onPause 调用 GameThread.endThread 结束 GameThread 并结束本次活动
  4. onTouch 将触摸事件传递给 GameThread.doTouch 方法

游戏线程.java:

  1. startThread 设置本地保存的数据,从文件加载 GameData 并启动线程
  2. run 是一个标准的游戏循环,为每一帧调用相当标准的 updatePhysics 和 drawScreen 例程。 游戏循环完成后,它会将 GameData 保存到文件中
  3. endThread 在运行中停止游戏循环并等待它完成
  4. 来自游戏活动的 doTouch 动作触摸事件

它似乎工作。 这确实意味着必须在一个线程中处理不同的屏幕(例如标题屏幕、选项、游戏和游戏结束),但这并不是世界末日,恕我直言。

也许我会在 CodeReview 上发布代码(如果我这样做,我会更新它),看看是否有人有任何意见。 同时,我最好开始编写下一个 Angry Birds 的代码!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM