libGDX系列-Android FrameWork层面遇到两个崩溃相关的问题修正

by AlexQ (email alexq_andr@163.com)

image

工程托管在此:GitHub

这套系统跟随应用上线后,由于实际应用的结构要远高于demo,线上crash统计会捕捉到不少我们demo中发现不了的问题,收集到很多崩溃、异常问题后,也一直在持续修改、更新,总结一下反思一下也还是有不少值得总结的问题。

1. 生命周期函数不要随意干预

崩溃日志如下:

 android.support.v4.app.SuperNotCalledException: Fragment 
 liveroomLibGDXFragment{64ab91f #0 id=0x7f0d00d6} 
 did not call through to super.onPause()

提示没有调用super.onPause()方法,来看看源代码以及设计原因

liveroomLibGDXFragment中的代码如下:

   @Override
    public void onPause() {

        super.onPause();

        //非销毁状态下,恢复继续展示
        if (!m_isDestorying)
            super.onResume(); //核心问题出在这里

但我们在demo中做退出操作,反复测试时未发现问题。

结论是不要随便调用生命周期方法。

这么做的原因当时设计时还特意做了解释。如下:

继承自AndroidFragmentApplication的子类中onPause处理,手动调用super.onResume,在我应该并能够看到特效的情况下,让动画别被frozen,连续的播放下去,如果在播放粒子特效时,突然由于用户点击,弹出一个dialog或者dialogstyle样式的activity(无论是半窗还是有透明度),我们此时一定是希望用户看到弹窗的同时,下面的粒子特效继续播放,这样的用户体验是连续的,视觉上也不是唐突的而是连贯的。那么如果我们不处理onPause的话,现象上会出现,粒子特效暂停了,frozen了,看一下libGDX中代码便知晓了,他在onPause时调用了this.graphics.pause();从而引起frozen了,只需要强制在此之后调用onResume即可,视觉效果上连续不间断,达到了我们的要求。

2. 深入源代码解决问题

崩溃日志如下:

java.util.ConcurrentModificationException问题

 Caused by: java.util.ConcurrentModificationException
    at java.util.HashMap$HashIterator.nextEntry(HashMap.java:787)
    at java.util.HashMap$KeyIterator.next(HashMap.java:814)
    at com.badlogic.gdx.graphics.Texture.getManagedStatus(Texture.java:285)
    at com.badlogic.gdx.backends.android.AndroidGraphics.logManagedCachesStatus(AndroidGraphics.java:541)
    at com.badlogic.gdx.backends.android.AndroidGraphics.clearManagedCaches(AndroidGraphics.java:536)
    at com.badlogic.gdx.backends.android.AndroidFragmentApplication.onPause(AndroidFragmentApplication.java:228)

引起这个问题的原因从错误日志上很明显是HashMap操作上由于增删操作冲突引起的偶先的崩溃。(在日活跃20w的app中发生概率为千分之三左右,量还是很大的)

我们分析一下libgdx源代码:

public static String getManagedStatus () {
        ...
        for (Application app : managedTextures.keySet()) {
            ...
        }
        ...
    }

问题就出在for循环上,两种方式解决此问题:

  1. try catch ConcurrentModificationException异常,但此方法可能只是忽略的了严重问题的出现;
  2. 使用迭代器解决此问题;(同学们可自行google “java 迭代器 ConcurrentModificationException”之类的);

已将此问题反馈给官方,但是没有得到回复。

神奇的是我自己编译了一遍libgdx源代码,发现代码此段代码会被自动优化成迭代器模式。另外,libgdx编译按照官网wiki上的说明即可,使用ant,真是超级方便。

2017-08-13 21:2236
  • www2017-08-22 10:57

    你好,没解决办法吗?

  • alexueqing2017-08-22 11:03

    解决方式已经在Github实例源码中了,主要是问题1结束特效的策略改动;问题2我重新修改编译了源代码。本次主要是总结了两个跟底层原理相关的问题,着重描述了问题。请见谅。