BroadcastReceiver 10秒 ANR

本文详细介绍了Android中的BroadcastReceiver组件,包括其工作原理、生命周期限制及如何正确处理耗时任务。此外还探讨了BroadcastReceiver与Service之间的协作方式。

在 Android中,程序的响应(Responsive)被活动管理器(Activity Manager)和窗口管理器(Window Manager)这两个系统服务所监视,当BroadcastReceiver在10秒内没有执行完毕,Android会认为该程序无响应,所以在 BroadcastReceiver里不能做一些比较耗时的操作,否则会弹出ANR(Application No Response)的对话框。如果需要完成一项比较耗时的工作,应该通过发送Intent给Service,由Service来完成,而不是使用子线程的方法来解决,因为BroadcastReceiver的生命周期很短(在onReceive()执行后BroadcastReceiver的实例就会被销毁),子线程可能还没有结束BroadcastReceiver就先结束了。如果BroadcastReceiver结束了,它的宿主进程还在运行,那么 子线程还会继续执行。但宿主进程此时很容易在系统需要内在时被优先杀死。因为它属于空进程(没有任何活动组件的进程)。

每次广播消息到来时,都会创建BroadcastReceiver实例来执行onReceive()方法。


广播接收者(BroadcastReceiver)用于接收广播Intent,广播Intent的发送是通过调用 Context.sendBroadcast()、Context.sendOrdeedBroadcast()、 context.sendStickyBroadcast()来实现的,通常一个广播Intent可以被订阅了此Intent的多个广播接收者所接收,这 个特性跟JMS中的Topic消息接收者类似,要实现一个广播接收者方法如下:

onReceive的生命周期为10秒,所以里面的操作不能超过10秒

 

This method is called when the BroadcastReceiver is receiving an Intent broadcast. During this time you can use the other methods on BroadcastReceiver to view/modify the current result values. This method is always called within the main thread of its process, unless you explicitly asked for it to be scheduled on a different thread using registerReceiver(BroadcastReceiver, IntentFilter, String, android.os.Handler). When it runs on the main thread you should never perform long-running operations in it (there is a timeout of 10 seconds that the system allows before considering the receiver to be blocked and a candidate to be killed). You cannot launch a popup dialog in your implementation of onReceive().

 

### Broadcast 超时导致 ANR 的时间限制 在 Android 系统中,广播接收器(BroadcastReceiver)执行时间过长可能会触发应用无响应(Application Not Responding, ANR)。具体来说,当主线程上的广播处理超过一定时限而未能完成操作时,系统会判定该进程进入 ANR 状态并弹出提示对话框[^1]。 对于前台广播而言,默认情况下其最大允许运行时间为 **10 **;而对于后台广播,则更为严格,仅限于 **5 **。一旦超出这些设定阈值,即便尚未完全耗尽 CPU 时间片,也会因违反响应性原则遭到惩罚机制干预[^2]。 另外值得注意的是,在某些特殊场景下比如设备处于低电量模式或者开发者主动调用了 `setExactAndAllowWhileIdle()` 方法安排定时任务期间,即使正常范围内也可能因为资源调度优先级调整而导致看似合理的逻辑被执行延后从而间接引发类似的超时现象[^3]。 --- ### 关于 Android 系统内存状态参数说明 #### MemTotal 参数解释 `MemTotal` 表达了整个物理 RAM 总量减去内核保留区域之后剩余可分配给用户空间程序使用的那部分存储容量大小,单位通常是千字节(KB)[^4]。 #### MemFree 参数解释 尽管名字直白地暗示着“空闲”,但实际上这里的 `MemFree` 数值往往偏低甚至趋近零也很常见,这是因为现代操作系统倾向于充分利用每一寸可用内存来做文件缓存等工作以提升性能效率的缘故所致[^5]。所以单纯依赖这一项来判断是否存在潜在的OOM风险并不科学合理。 #### MemAvailable 参数解释 相比之下,`MemAvailable` 才能更好地反映出当下可供新申请分配的真实有效余量估计值,它综合考量了包括但不限于页面高速缓存(Page Cache),slab 分配对象(Slab Allocations)等多种因素共同作用下的最终结果呈现形式[^6]。 以下是获取上述三项核心指标的一个简单 Python 实现例子: ```python def fetch_android_mem_status(): mem_info = {} with open("/proc/meminfo", "r") as file: for line in file: parts = line.strip().split(":") key = parts[0].strip() value_kb = int(parts[1].replace("kB","").strip())*1024 # Convert to Bytes if key == 'MemTotal': mem_info['mem_total_bytes'] = value_kb elif key == 'MemFree': mem_info['mem_free_bytes'] = value_kb elif key == 'MemAvailable': mem_info['mem_avail_bytes'] = value_kb return mem_info if __name__ == "__main__": memory_details = fetch_android_mem_status() print(f"Memory Total: {memory_details.get('mem_total_bytes')} bytes") print(f"Memory Free : {memory_details.get('mem_free_bytes')} bytes") print(f"Memory Available:{memory_details.get('mem_avail_bytes')} bytes") ``` 以上代码片段展示了如何从 `/proc/meminfo` 文件读取必要的字段并将它们转换成易于理解和比较的标准字节数量级表示法。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值