得到低内存警告,但我似乎没有泄漏内存

时间:2012-06-28 19:42:45

标签: android android-activity android-lifecycle

我的应用程序正在关闭,没有任何错误消息,并在切换活动大约20或30次后自动重新启动。我正在通过点击一个按钮来测试这一点,该按钮使用不同的数据重新启动当前活动(并在达到数据结束时循环回到开头)。该活动使用FLAG_ACTIVITY_CLEAR_TOP标志启动,因此一次只能在内存中存在一个活动实例。如果我设置FLAG_ACTIVITY_NO_HISTORY,问题仍然存在。

当应用程序崩溃时,它出现在logcat输出中:

06-28 19:32:10.472: I/ActivityManager(115): Process com.mypackage.myapp (pid 3718) has died.
06-28 19:32:10.476: I/WindowManager(115): WIN DEATH: Window{406d06e0 com.mypackage.myapp/com.mypackage.myapp.welcome.LoginActivity paused=false}
06-28 19:32:10.480: E/InputDispatcher(115): channel '406ade20 com.mypackage.myapp/com.mypackage.myapp.matchup.MatchUpActivity (server)' ~ Consumer closed input channel or an error occurred.  events=0x8
06-28 19:32:10.480: E/InputDispatcher(115): channel '406ade20 com.mypackage.myapp/com.mypackage.myapp.matchup.MatchUpActivity (server)' ~ Channel is unrecoverably broken and will be disposed!
06-28 19:32:10.535: I/WindowManager(115): WIN DEATH: Window{406ade20 com.mypackage.myapp/com.mypackage.myapp.matchup.MatchUpActivity paused=false}
06-28 19:32:10.539: I/WindowManager(115): WIN DEATH: Window{407a8230 com.mypackage.myapp/com.mypackage.myapp.fightcard.FightCardActivity paused=false}
06-28 19:32:10.566: I/ActivityManager(115): Start proc com.mypackage.myapp for activity com.mypackage.myapp/.fightcard.FightCardActivity: pid=3915 uid=10053 gids={3003}
06-28 19:32:10.574: I/ActivityManager(115): Low Memory: No more background processes.

通常这会告诉我应用程序正在泄漏内存,但是如果我在Eclipse中观察DDMS透视图时执行此测试,我可以看到分配的内存是稳定的,实际上应用程序通常会崩溃,即使使用的百分比约为50%(大部分时间都在这里)。堆大小和分配的内存不会增加。

我在应用程序上广泛使用MAT,虽然我之前确实发现了内存泄漏,但我已经解决了这些问题,并且无法再找到该工具的任何其他问题。

我已经能够在运行Gingerbread的Nexus S上重新创建这个问题,但它似乎在运行4.0.4的Galaxy Nexus上不可重现(但这可能是由于堆更大的事实)在银河上。)

我错过了什么?

1 个答案:

答案 0 :(得分:3)

上面提到David Wasser的建议让我得到了解决方案。我注意到当我运行上面提到的命令时,我得到了一大堆自定义字体资产分配:

zip:/data/app/com.mypackage.myapp-2.apk:/assets/DINNextLTPro-MediumCond.otf: 98K

随着我改变活动,这些分配似乎增长得非常快。一些谷歌搜索引导我到这个链接:http://code.google.com/p/android/issues/detail?id=9904

因此,似乎存在与使用自定义字体相关的Android错误。以下解决方法来自上面的链接:

public class Typefaces {
    private static final String TAG = "Typefaces";

    private static final Hashtable<String, Typeface> cache = new Hashtable<String, Typeface>();

    public static Typeface get(Context c, String assetPath) {
        synchronized (cache) {
            if (!cache.containsKey(assetPath)) {
                try {
                    Typeface t = Typeface.createFromAsset(c.getAssets(),
                            assetPath);
                    cache.put(assetPath, t);
                } catch (Exception e) {
                    Log.e(TAG, "Could not get typeface '" + assetPath
                            + "' because " + e.getMessage());
                    return null;
                }
            }
            return cache.get(assetPath);
        }
    }
}

基本上我们正在缓存自定义字体资产的实例,因此每个实例只需要实例化一次。