ContentObserver 与 BroadCastReceiver:电池使用情况、内存、CPU?

Posted

技术标签:

【中文标题】ContentObserver 与 BroadCastReceiver:电池使用情况、内存、CPU?【英文标题】:ContentObserver vs. BroadCastReceiver : Battery Usage, Ram, CPU? 【发布时间】:2012-08-31 20:35:11 【问题描述】:

由于对应用程序的电池使用、内存和 cpu 使用有如此必要的关注,所以多个内容观察器与多个广播接收器的开销是多少?

示例 1:

使用 5 个内容观察器以 START_STICKY 运行的服务 正确注册/注销。

示例 2:

从清单中设置的 5 个广播接收器触发的服务。

示例 3:

使用 START_STICKY 运行的服务使用 5 个已注册 广播接收器。

观察者和接收者在电池使用/内存/cpu 方面的真正区别是什么?任何专业人士都可以对此发表意见吗?我假设 1 个实例不会产生太大影响,但让我们以上面的示例为例,同时运行 5 个。

【问题讨论】:

服务运行比清单接收器占用更多 RAM,因为无论如何运行的系统进程都会跟踪它们。正在运行的服务需要您的应用程序进程正在运行。其余的应该是相当的,因为仅仅等待事件并不涉及真正的 cpu / 电池使用。 @zapl:感谢您的回答。我不熟悉底层结构。我假设他们都使用回调,因此使用相同的资源量? receivers 和 oberservers 都应该使用主线程循环器/消息队列机制,它将所有事件传递到您的应用程序并调用所有onCreateonTouch 等方法。这也应该适用于onContentChangedonReceive。当什么都没有发生时,主线程只是等待,所以 IMO 两者之间没有区别。 @zapl:您应该将此作为答案,以便将其标记为已接受。除非其他人有更好的答案,否则我认为您几乎涵盖了它。 【参考方案1】:

Service 运行 vs 没有 Service 运行

每个应用程序至少有一个Process 在您的应用程序运行时启动。该过程至少使用一些内存,人们喜欢使用任务杀手来释放它,尽管 android 会在实际需要内存时自动执行此操作。这个内存对于Service的情况来说绝对是一个劣势。

CPU / 电池使用率仅在发生某些事情并因此主动使用 CPU 或当您的应用强制系统保持资源启用时才会增加,例如当您保留WakeLock 时。如果您不执行任何此操作,则您的应用程序使用大约 0 CPU / 电池,并且其行为就像一个停止的应用程序,它保存在内存中以加快重新启动它的速度。如果您的代码正在运行,那么您无意中使用某些资源的可能性肯定会更高。

如果根本没有 Service / Activity 正在运行,而您只需在清单中注册一个 BroadcastReceiver,您基本上就是告诉系统将您的接收器包含在它在发送广播时检查的接收器列表中。非常少的额外工作。

Manifest 接收器还有一个优势,即当内存压力很高时系统不会被杀死。那些接收器只是工作,你根本不需要关心。如果你愿意,你甚至可以enable / disable他们。

ContentObserverBroadcastReceiver

两者都应该使用ActivityThread / Looper / MessageQueue 机制,通常称为“UI 线程”,它将所有事件传递到您的应用程序并调用所有onCreateonTouch 等方法。当您在这些方法中出现问题时查看堆栈跟踪时很容易看到:

AndroidRuntime(521): FATAL EXCEPTION: main
AndroidRuntime(521): java.lang.RuntimeException: MotionEvent405215b0 action=0 x=66.0 y=78.0 pressure=1.0 size=0.0 recycled twice!
AndroidRuntime(521):     at android.view.MotionEvent.recycle(MotionEvent.java:659)
AndroidRuntime(521):     at android.view.ViewRoot.handleMessage(ViewRoot.java:1880)
AndroidRuntime(521):     at android.os.Handler.dispatchMessage(Handler.java:99)
AndroidRuntime(521):     at android.os.Looper.loop(Looper.java:123)
AndroidRuntime(521):     at android.app.ActivityThread.main(ActivityThread.java:3647)

如果没有广播或内容更改通知将被传递,该线程只是等待。等待不使用 CPU(即一直在循环中主动循环),但告诉系统它不需要为该线程安排处理时间。那时 CPU 使用率实际上约为 0。因此,IMO 在运行时注册两者之一完全没有区别。

唯一可以为其中一种方法带来优势的区别是,如果这些方法更频繁地触发。

1 对 5 个

没关系。系统中有太多的接收者/观察者,添加 1 或 5 并不重要。如果添加 1000 左右,您可能会注意到

附带说明:不要阻止 UI 线程执行它的工作。尽管接收器和服务没有 UI,但它们的回调方法在 UI 线程上执行。因此,如果您执行任何长时间运行的操作,例如在任何 onReceive / Service#onCreate 等方法中下载内容,这将导致 ANRs 的方式与它相同,例如在Activity#onCreate

【讨论】:

以上是关于ContentObserver 与 BroadCastReceiver:电池使用情况、内存、CPU?的主要内容,如果未能解决你的问题,请参考以下文章

用于监听联系人变化的 ContentObserver

短信 ContentObserver onChange() 触发多次

ContentObserver 每行实现

ContentObserver onChange

为啥 ContentObserver 会被多次调用?

从 ContentObserver 获取触发器