How to fix OpenGL ES application crashes when moving to the background

本文详细介绍了iOS系统中OpenGL ES应用在切换到后台时的渲染限制及可能导致的应用终止问题,并给出了确保应用稳定运行的建议措施。

对于iOS应用 OpenGL的渲染如在在应用进入后台后仍在渲染 则APP会crash


iOS apple 官方文档


Background Apps May Not Execute Commands on the Graphics Hardware

An OpenGL ES app is terminated if it attempts to execute OpenGL ES commands on the graphics hardware. iOS prevents background apps from accessing the graphics processor so that the frontmost app is always able to present a great experience to the user. Your app can be terminated not only if it makes OpenGL ES calls while in the background but also if previously submitted commands are flushed to the GPU while in the background. Your app must ensure that all previously submitted commands have finished executing before moving into the background.

If you use a GLKit view and view controller, and only submit OpenGL ES commands during your drawing method, your app automatically behaves correctly when it moves to the background. The GLKViewController class, by default, pauses its animation timer when your app becomes inactive, ensuring that your drawing method is not called.

If you do not use GLKit views or view controllers or if you submit OpenGL ES commands outside a GLKView drawing method, you must take the following steps to ensure that your app is not terminated in the background:

  1. In your app delegate’s applicationWillResignActive: method, your app should stop its animation timer (if any), place itself into a known good state, and then call the glFinish function.

  2. In your app delegate’s applicationDidEnterBackground: method, your app may want to delete some of its OpenGL ES objects to make memory and resources available to the foreground app. Call the glFinish function to ensure that the resources are removed immediately.

  3. After your app exits its applicationDidEnterBackground: method, it must not make any new OpenGL ES calls. If it makes an OpenGL ES call, it is terminated by iOS.

  4. In your app’s applicationWillEnterForeground: method, re-create any objects and restart your animation timer.

To summarize, your app needs to call the glFinish function to ensure that all previously submitted commands are drained from the command buffer and are executed by OpenGL ES. After it moves into the background, you must avoid all use of OpenGL ES until it moves back into the foreground.




Thread 0 name: Dispatch queue: com.apple.main-thread
Thread 0 Crashed:
0   libGPUSupportMercury.dylib    	0x30570094 gpus_ReturnNotPermittedKillClient + 0
1   libGPUSupportMercury.dylib    	0x305700ae gpus_KillClient ( )
2   libGPUSupportMercury.dylib    	0x305705ba gpusSubmitDMABuffers ( )
3   IMGSGX535GLDriver             	0x34bd29b8 SubmitPacketsIfAny ( )
4   IMGSGX535GLDriver             	0x34bd2ad0 glrFlushContextToken ( )
5   GLEngine                      	0x37719c4a gliPresentViewES ( )
6   OpenGLES                      	0x323df6b4 -[EAGLContext presentRenderbuffer:] ( )
...
...

可以参看此文档 https://developer.apple.com/library/content/documentation/3DDrawing/Conceptual/OpenGLES_ProgrammingGuide/ImplementingaMultitasking-awareOpenGLESApplication/ImplementingaMultitasking-awareOpenGLESApplication.html#//apple_ref/doc/uid/TP40008793-CH5-SW1

但是并没有给出解决办法 还是在进入后台时停止所有的OpenGL渲染吧。

参考:https://developer.apple.com/library/content/qa/qa1766/_index.html

<think>嗯,用户现在问的是关于在Android开发中多次调用super.onCreate()可能导致崩溃的问题。首先,我需要回顾一下Activity的生命周期,尤其是onCreate()方法的作用。 用户之前的问题是关于setSupportActionBar的使用位置,现在转向了生命周期方法中的super调用。这可能意味着他们在实际编码中遇到了重复调用super.onCreate()的情况,或者看到了相关的代码示例,担心其影响。 我需要确定用户的使用场景。他们可能是在自定义Activity时,不小心在onCreate()里多次调用了super.onCreate(),或者在重写其他生命周期方法时遇到了类似的问题。也有可能在继承结构复杂的Activity子类中,父类已经调用了super,而子类再次调用,导致问题。 接下来,我需要解释为什么多次调用super.onCreate()会导致崩溃。Android框架期望每个生命周期方法只被调用一次,重复调用会破坏内部状态管理。例如,super.onCreate()会初始化窗口、恢复Fragment状态等,多次执行可能引发异常,如FragmentManager的状态不一致或视图重复加载。 还要考虑用户可能的误区,比如误以为必须显式调用父类方法多次,或者在条件语句中不小心调用了。需要明确说明正确的做法是只调用一次,并且通常是在方法的最开始。 另外,用户可能遇到的错误类型有哪些?比如IllegalStateException、NullPointerException,或者界面重复绘制的问题。需要给出具体的错误示例和排查步骤,帮助他们识别和修复问题。 最后,是否需要提供代码示例来对比正确和错误的做法?这有助于用户更直观地理解。同时,提醒他们在重写其他生命周期方法时也要遵循同样的规则,比如onStart(), onResume()等,避免同样的问题发生。 总结回答结构:首先明确问题原因,然后说明正确的调用方式,接着列举常见错误和异常,最后给出解决方案和预防措施。这样用户能逐步理解问题所在,并知道如何修正和避免。</think>在Android开发中,`super.onCreate()` **必须且只能调用一次**,这是Activity生命周期管理的核心规则。以下是深度解析: --- ### **崩溃原理** $$ \text{Activity生命周期状态机} \rightarrow \text{重复调用导致状态异常} $$ 1. **系统预期行为**:Android框架通过`super.onCreate()`实现: - 初始化窗口属性(Window/DecorView) - 恢复Fragment状态(通过`FragmentController`) - 触发`ViewModel`的创建 2. **重复调用后果**: - $\text{FragmentManager}$抛出`IllegalStateException: "Already attached"` - $\text{Window}$相关操作重复执行(如`setContentView()`多次加载布局) - 可能引发`NullPointerException`(未正确恢复的引用) --- ### **正确代码模式** ```java protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // ✅ 必须且唯一的调用位置 setContentView(R.layout.activity_main); // 其他初始化代码... } ``` --- ### **常见错误场景** 1. **条件误判**: ```java if (condition1) { super.onCreate(savedInstanceState); // ❌ 可能被多次触发 } if (condition2) { super.onCreate(savedInstanceState); // ❌ } ``` 2. **继承链错误**: ```java class BaseActivity extends AppCompatActivity { protected void onCreate(Bundle bundle) { super.onCreate(bundle); // ✅ 父类调用 } } class ChildActivity extends BaseActivity { protected void onCreate(Bundle bundle) { super.onCreate(bundle); // ✅ 正确继承 super.onCreate(bundle); // ❌ 子类重复调用 } } ``` --- ### **崩溃日志特征** ```logcat E/AndroidRuntime: FATAL EXCEPTION: main Process: com.example.app, PID: 12345 java.lang.IllegalStateException: at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3654) Caused by: java.lang.IllegalStateException: FragmentManager is already executing transactions ``` --- ### **解决方案** 1. **代码审查**:检查所有重写的方法,确保`super.xxx()`只出现一次 2. **使用Lint工具**:Android Studio会标记$\text{"Overriding method should call super.xxx() exactly once"}$ 3. **继承规范**: - 父类中调用`super.onCreate()`后,子类**无需也不应**再次调用 - 若使用AOP(如AspectJ),需确保切面逻辑不会重复触发 --- ### **延伸至其他生命周期方法** 同规则适用于: - `onStart()` / `onStop()` - `onResume()` / `onPause()` - `onDestroy()`(尤其注意避免重复释放资源) 例如,在`onDestroy()`中多次调用`super.onDestroy()`可能导致: $$ \text{Memory Leak} \leftarrow \text{资源未正确释放} \quad \text{vs} \quad \text{NPE} \leftarrow \text{资源被重复释放} $$
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值