我有一些代码在我启动 android 活动时运行。如果需要,我将从共享首选项和网络服务器中读取。其中一些将发生在主线程上,显然服务器请求位于 AsyncTask 中。
现在我想知道的是,如果应用程序暂停会发生什么。字节码是在程序计数器所在的地方停止还是等待主循环上发生的任何事情完成然后调用 onPause。
此外,我担心包括从网络接收数据时回调会发生什么。回调可以在暂停恢复后发生还是会一直丢失?据我了解,在活动暂停时,从网络读取的线程仍然可以运行。
我有一些代码在我启动 android 活动时运行。如果需要,我将从共享首选项和网络服务器中读取。其中一些将发生在主线程上,显然服务器请求位于 AsyncTask 中。
现在我想知道的是,如果应用程序暂停会发生什么。字节码是在程序计数器所在的地方停止还是等待主循环上发生的任何事情完成然后调用 onPause。
此外,我担心包括从网络接收数据时回调会发生什么。回调可以在暂停恢复后发生还是会一直丢失?据我了解,在活动暂停时,从网络读取的线程仍然可以运行。
好吧,我已经做了一些实验,看了一眼 Activity 的 Android 源代码,现在我更清楚了。
我发现的东西:
onPause、onResume、onStart、onCreate 等都在同一个线程(通过打印Thread.currentThread.getId()
)内运行,该线程是主事件线程,并且这个单一事件线程用于所有活动(除非您在清单中分配了一个新进程)。这并不完全出乎意料,但我确实想知道例如 onPause 是否可能存在于用于停止活动的系统启动线程中。
如果您的代码中有一个无限的 while(比如在 onResume 或由于按下按钮而执行的代码中),那么 onPause 和其余部分将永远不会被执行。此外,该循环将继续执行,例如,每秒打印到日志中。如果您要进入主屏幕(或任何其他应生成 onPause 甚至 onStop 的内容),这些打印仍然会发生,并且尽管应用程序不可见,但循环仍在继续。您仍将转到主屏幕。如果你愿意,你可以回到你的应用程序,它仍然会卡在它的循环中。因此,当文档谈到暂停或停止活动的操作时,显然这不会停止应用程序的执行,或者在主线程中(在调用 onPause 之前)或其他任何内容中生成运行时异常。
如果我在 AsyncTask 中运行缓慢的 Web 请求,则该 asynctask 代码将在不同的线程中运行,正如您所期望的那样。如果启动任务的 Activity 在任务完成之前暂停,并且 onPause、onStop 被正常调用,那么当 asynctask 完成它的回调(在 Activity 中定义)时,onPostExecute 仍将被调用并执行,在主图形用户界面线程。尽管“活动”已经完全停止了。
我由此得出的结论是,所有 onStop 和 onStart 等都是主事件循环中的简单事件,就像其他任何事件一样,必须等待轮到它们在主线程中调用。它们没有什么特别的,不会立即执行或类似的东西,并且可以被循环中的任何其他东西阻塞。
此外,Activity 的概念实际上只是一个 GUI 事物,如果 Activity 停止,则没有屏幕或按钮可以与之交互或显示事物。但是,这对将继续处于活动状态并可以打印或响应回调等的底层进程没有影响。JVM 继续并且它的所有类继续存在并且进程继续执行。显然,如果没有从 GUI 接收任何事件或交互并且接收到 onPause,它应该什么都不做。如果它确实占用了任何类型的资源,那么这个过程当然可以被关闭——这就是你应该实现生命周期回调的原因。
顺便说一句,我们可以在 Activity.java 中看到暂停是通过调用
final void performPause() {
mFragments.dispatchPause();
mCalled = false;
onPause();
mResumed = false;
然后到
protected void onPause() {
if (DEBUG_LIFECYCLE) Slog.v(TAG, "onPause " + this);
getApplication().dispatchActivityPaused(this);
mCalled = true;
}
这表明正如测试所预期的那样,暂停实际上只是将另一个事件分派到主循环。
我认为 mCalled 变量有两种用途 - 一种是确保在您的 Activity 派生类中调用了 super() 版本,另一种是让系统在销毁需要资源的进程之前检查它是否被调用。
鉴于这是如何工作的,如果 onPause 很慢,或者被偶数循环中的其他东西阻塞,则可能是您的进程在 onPause 完成之前被杀死。
显然,其中一些对某些人来说可能是显而易见的。但是我发现文档很混乱。如果不了解运行、暂停等概念在代码排序方面的实际含义,我无法推断我的代码可能进入的状态,因为我认为暂停可能意味着无论 gui 线程正在做什么,都会出现运行时异常。
如果我完全误解了这一点并且得到了错误的想法,请告诉我!我只使用了 Android 2.5 周,很可能我很困惑!