最简单的 Android Activity 生命周期

发布于 2024-10-29 04:10:34 字数 1093 浏览 7 评论 0原文

我注意到自从我启动应用程序以来,Android 开发者活动部分已经更新,但我仍然不清楚最简单的活动生命周期是什么。

据我所知:

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

该 Activity 可能会在 onPause 之后随时删除,因此我应该将整个应用程序状态保存到 onPause 文件中,而不是依赖 onStop 或 onDestroy。此外,onSaveInstanceState 不会在每次 onPause 之前调用,因此并不值得使用。

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

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

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

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

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

有什么想法吗?

更新: 我想我想到的是“首页”活动调用游戏活动。当玩家点击“Play”时,首页活动将调用游戏活动

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

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

我也是这么想的,请问有道理吗?

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

它不支持 Android 活动生命周期“已暂停”和“已停止”状态。一旦不再显示,它就会自行终止并必须手动重新启动,但它确实会从您上次中断的地方继续执行!

I noticed that the Android Developers Activity section has been updated since I started my app, but I am still unclear what the simplest Activity Lifecycle is.

As far as I can make out:

onCreate, onResume and onPause are the essential ones.

The activity may be deleted any time after onPause, so I should save my whole app state to a file onPause and not rely on onStop or onDestroy. Also, onSaveInstanceState is not called before every onPause so is not really worth using.

Rather than trying to write loads of code to handle all the scenarios, why not destroy the Activity at the end of its onPause?

The Lifecycle would then be onCreate and onResume before it is active, then onPause when it becomes inactive. Other methods would not be needed.

I'd use onCreate to call setContentView and set up view listeners, but everything else would be put in onResume, including loading the restored state from a file?
As stated earlier, onPause would save the state to a file and destroy the activity.

As far as I can see, the only disadvantage of this might be that when a popup is on screen, the activity is deleted and has to be recreated when the popup is closed, meaning the activity won't be visible behind the popup (although I have not tested this)

It may take a bit longer to restart the activity, but since the system could have deleted the activity anyway without any notice, you have to save the whole state anyway.

Any thoughts?

Update:
I suppose what I was thinking of was where a 'front page' activity calls a game activity. The frontpage activity would call the game activity when the player clicks 'Play'

The game activity would set up its views and listeners etc. in onCreate, and in onResume it would load a file containing the game state, or start a new game if no file existed.

onPause of the game, it writes the game state to the file, then whatever happens to the game activity (nothing, or gets stopped/destroyed, or whatever) the onResume method would always load all the data back in again from the file.

That's sort of what I was thinking, if that makes any sense?

Update2:
I've devised a simple solution which I've documented in an answer below, if anyone's interested!

It doesn't support the Android Activity Lifecycle 'Paused' and 'Stopped' states. Once it is no longer displayed it kills itself and has to be restarted manually, but it does carry on from where you left off!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

御弟哥哥 2024-11-05 04:11:40

根据@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() 中添加了另一个方法,您也会看到该方法。这意味着,你的类状态(即快照)取决于你,你一次又一次地做什么,你不断更新你的快照。

The mature, full-featured and full functional Android app gets transitioned (state = function of time) according to the answer provided by @Felix.

But what if you just want to create an app which doesn't even have GUI. And you want the simplest lifecycle then I have the answer below.

This answer probably you would find interesting. Android system after reading AndroidManifest.xml knows which is entry point. Whichever activity has this

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

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

will be the starting or entry point for the system to start with. After this, your app process got the memory where it can start itself.

Your main process creation is the task of Android system. When an application component starts and the application does not have any other components running, the Android system starts a new Linux process. After the process calls the onCreate(), it creates main thread. That's the reason why you must call onCreate(), because the main thread is then initialized and the main thread is the trigger for all of your future actions.

On onCreate(), you got your main thread. After that, it is totally up to you, what callbacks you want to call. There is no rule you must call onStart() after onCreate().

Only one lifecycle method onCreate() is guaranteed to be your component's life cycle back.

And, furthermore, to understand, what each lifecycle method is doing inside it, put the below code.

//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

So, always add above same code to view logs in log cat console.

When your app starts GUI, it calls onStart(). If you don't call super() method inside the callback, android system shows broken pipe error and it can't do further processing and debugging.

enter image description here

But, you can implement your own logic inside each callback method. Eg, you can do summation of two numbers on onStart().

So, all android callback methods are partially implemented methods. They are not purely abstract methods because you should call the super() method inside them.

The attached picture tells: Application main process calls onCreate(), it delegates it's responsibilities to main thread (UI thread) and main thread calls these 16 other callbacks.

enter image description here

Further, if you would like to see all of your methods at particular time, put this below code.

//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.

In my scenario, from the just above code snippet, I see it has called 375 methods.

Note: If you had added another method inside onCreate() before you print all of your methods using just above code snippet, you would have seen that method as well. It means, your state of the class (i.e., snapshot) is according to you, what you do time after time, you keep updating your snapshot.

以酷 2024-11-05 04:11:35

Android 应用程序中有 7 种管理 Activity 生命周期的方法:

  1. onCreate()
  2. onStart()
  3. onResume()
  4. onRestart()
  5. onPause()
  6. onStop()
  7. onDestroy()

我已经在 我的博客

There are 7 methods that manage the activity lifecycle in Android application:

  1. onCreate()
  2. onStart()
  3. onResume()
  4. onRestart()
  5. onPause()
  6. onStop()
  7. onDestroy()

I have written more in-depth about these methods on my blog

趁年轻赶紧闹 2024-11-05 04:11:29

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

What i personally think is developer should divide the work into different states of the activity. Sequence of the work must be retained in this case what is more importent I think of and this is why because Android can't handle a long UI processing in a single thread & it gives error that Android have 'so much work to do' in this reference that could be cause of getting crash sometimes So we should prevent to write whole code in a section. The code would be written into difference functions or classes and we can derive these functions as per requirement. Thanks.

笑着哭最痛 2024-11-05 04:11:20

我想我已经找到了我正在寻找的东西! (Me 1, Bono 0)

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

如果应用程序失去焦点(即来电或用户单击返回等),Game 会将 GameData 保存到文件中并退出。要恢复,只需再次启动应用程序,它就会立即返回到您上次停止的位置。

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

Game.java:onCreate

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

GameThread.java:startThread

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

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

也许我会在 CodeReview 上发布代码(如果我这样做的话我会更新它)并看看是否有人有任何评论。与此同时,我最好开始编写下一款《愤怒的小鸟》的代码!

I think I have found what I am looking for! (Me 1, Bono 0)

This is for a single 'Game' activity which uses minimum methods to control a 'GameThread' thread which handles the game. It uses an additional 'GameData' class to hold data which is required to be persistent between activations.

If the app loses focus (i.e. an incoming phone call, or the user clicks back etc.), Game saves the GameData to a file and exits. To resume, just start the app again and it goes right back to where you left off.

The layout file 'game.xml' is a SurfaceView covering the whole screen

Game.java:

  1. onCreate sets up the SurfaceHolder for the SurfaceView and creates the GameThread
  2. surfaceChanged calls GameThread.startThread to start the GameThread, if not already started, passing the screen size
  3. onPause calls GameThread.endThread to end the GameThread and ends this activity
  4. onTouch passes touch events to the GameThread.doTouch method

GameThread.java:

  1. startThread sets up locally held data, loads GameData from file and starts the thread
  2. run is a standard game loop, calling fairly standard updatePhysics and drawScreen routines for each frame. After the game loop finished it saves the GameData to the file
  3. endThread stops the game loop in run and waits for it to finish
  4. doTouch actions touch events from the Game activity

It seems to work. It does mean having to handle different screens (e.g. title screen, options, play and game over) in the one thread, but that's not the end of the world, IMHO.

Maybe I'll publish the code on CodeReview (I'll update this if I do) and see if anyone's got any comments. Meanwhile, I'd better get coding the next Angry Birds!

仅冇旳回忆 2024-11-05 04:11:13

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

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

onCreate() obviously first. Your activity can then enter onPause(). From there it could either onResume() or onDestroy(). That's the simplest path through the lifecycle that I know of.

I had an activity that didn't have an onPause() method. Through an odd series of events I noticed in DDMS that my app wasn't visible, but it was still requesting freshAds from AdMob :) Nice battery sucker. That's since been resolved but reminded me how important the simple things are.

浅沫记忆 2024-11-05 04:11:09

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

Android 总是会按照预期的方式调用每个回调,除非在某些情况下。

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

The answer is as simple as the life cycle. Only override callbacks when you need to handle stuff in there.

Android will always call every callback how it is supposed to, except in certain circumstances.

Just because certain callbacks are not guaranteed to be called doesn't mean that they are useless. Just don't try to handle sensible stuff in such callback methods.

远山浅 2024-11-05 04:11:04

我正在研究 Activity 生命周期以及从 onCreate 开始启动任何 Activity 时发生的完整过程。这里有一个 UML 图可以帮助你。

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

在此处输入图像描述

I was studying the activity life cycle and the complete process of what happens when you start any activity, starting from onCreate. Here is a UML diagram to help you.

Click this link to see a High Resolution version.

enter image description here

剩余の解释 2024-11-05 04:10:58

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

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

Android system is handling the lifecycle: i.e. instantiating activities and calling lifecycle methods. So I don't know what you mean by "destroy the activity". You, as a developer, have no such ability.

Second, activity lifecycle flow can be sometimes confusing (I know I struggled with it at the beginning). So, just implement all lifecycle methods and put logging statements in them. Then try all real-life use cases (including receiving a call during app use) to see how lifecycle methods are called.

旧瑾黎汐 2024-11-05 04:10:48

您在找这个吗?

Activity Lifecycle

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

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

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

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

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

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

  1. 当他们离开您的 Activity 并稍后返回时,他们希望它处于与离开时完全相同的实例中(这可以使用 onSaveInstanceStateonSaveInstanceState< /代码>)。他们并不期望他们退出您的活动。然而:
  2. 他们希望他们输入的数据能够被持久化(这将在onPause中完成)。例如,如果他们开始撰写消息,则即使他们退出活动,他们也希望下次回来时将其视为草稿。

您应该了解如何使用这些方法才能获得用户的期望。您实际如何使用它们取决于您、您的需求以及应用程序的性质。

Are you looking for this?

Activity Lifecycle

To further answer your question, yes, as you can plainly see from the above diagram the "simplest" (i.e. smallest number of method calls) lifecycle is indeed onCreate(); onStart(); onResume(); onPause();.

You should also know about onSaveInstanceState() and onRetainNonConfigurationInstance(). These are NOT lifecycle methods.

All these methods are very well documented. Please read this documentation thoroughly.

To clarify things further, here are a couple of real-life scenarios:

  1. Activity is running, other activities come on top of it, onPause is called. System runs out of memory, calls onSaveInstanceState, kills activity. User pressed back a few times, activity has to be re-instantiated (preferably using the data saved in onSaveInstanceState).
  2. Activity is running, user presses back. At this point onPause->onDestroy are called, without calling onSaveInstanceState.

You should understand the essential difference between onPause and onSaveInstanceState. The former is always called, while the latter is only called when the activity instance might be re-instantiated in the future. Following this train of thought, your users will expect two things:

  1. When they navigate away from your Activity and later come back to it, they want it in the exact same instance that they left it (this would be achieved using onSaveInstanceState). They don't expect that if they exit your activity. However:
  2. They will expect that data they have entered will be persisted (which will be done in onPause). For example, if they started composing a message, they'll expect to see it as a draft the next time they come back, even if they exited the activity.

You should understand how these methods are supposed to be used in order to get what your users expect. How you actually use them is up to you, your needs, and your app's nature.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文