【发布时间】:2016-10-23 05:30:15
【问题描述】:
我正在尝试在运行时更改活动的样式。
但我在重新创建活动期间面临使用内存增加的问题。
为了改变风格,我定义了一些主题并在活动中为它们初始化int array:
private int themes[] = new int[]{R.style.AppThemeOrange, R.style.AppThemeTeal,...};
为了设置下一个主题,我在首选项中保存了主题 ID 并重新启动了活动。然后在onCreate 方法中,我从首选项设置主题:
setTheme(PreferencesManager.getInstance().getAppTheme());
这是我改变主题的方法:
public void changeTheme() {
PreferencesManager.getInstance().setAppTheme(themes[(getCurrentThemePos() + 1) % themes.length]);
recreate();
}
在每次重新创建活动后,分配的内存堆增加了 0.1-0.2mb。因此,如果我多次更改应用程序主题,我会收到 Out Of Memory 错误。这是我的内存监视器:
仅在更改主题 1 分钟后,我将内存堆从 10 增加到 25 mb。
我尝试使用意图将recreate() 替换为重新启动活动,但结果是一样的:
public void changeTheme() {
PreferencesManager.getInstance().setAppTheme(themes[(getCurrentThemePos() + 1) % themes.length]);
Intent intent = new Intent(getApplicationContext(), UsersActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
finish();
}
我还尝试了AndroidManifest 中的所有可用值launchMode。没有效果。
我将所有出现的“this”更改为“getApplicationContext()”。仅在 xml 文件中保留根布局。
这是similar problem。但是那里有两个活动。就我而言,如果我使用
Intent i = new Intent(getApplicationContext(), UsersActivity.class);
i.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
startActivity(i);
activity 不会重新创建,因为它已经可见,并且不会调用 onCreate() 并且不会更改主题。
我也尝试在onDestroy() 中调用System.gc();,但内存使用量还是增加了。
这是我的styles.xml 文件的片段:
<style name="ChangebleTheme" parent="Theme.AppCompat.Light.NoActionBar">
<item name="android:windowAnimationStyle">@style/WindowAnimationTransition</item>
<item name="android:editTextStyle">@style/EditTextStyle</item>
<item name="editTextStyle">@style/EditTextStyle</item>
<item name="android:buttonStyle">@style/ButtonStyle</item>
<item name="buttonStyle">@style/ButtonStyle</item>
<item name="android:checkboxStyle">@style/CheckboxStyle</item>
<item name="checkboxStyle">@style/CheckboxStyle</item>
<item name="switchStyle">@style/SwitchStyle</item>
<item name="alertDialogProTheme">@style/Theme.AlertDialogPro.Material.Light</item>
</style>
<style name="AppThemeOrange" parent="ChangebleTheme">
<item name="main_theme_color">@color/colorAccentOrange</item>
<item name="main_theme_color_dark">@color/colorAccentDarkOrange</item>
<item name="colorAccent">@color/colorAccentOrange</item>
<item name="colorPrimaryDark">@color/colorAccentDarkOrange</item>
<item name="android:navigationBarColor">@color/colorAccentOrange</item>
<item name="ab_divider_style">@style/AppThemeOrange.ActionBarDivider</item>
</style>
<style name="AppThemeTeal" parent="ChangebleTheme">
<item name="main_theme_color">@color/colorAccentTeal</item>
<item name="main_theme_color_dark">@color/colorAccentDarkTeal</item>
<item name="colorAccent">@color/colorAccentTeal</item>
<item name="colorPrimaryDark">@color/colorAccentDarkTeal</item>
<item name="android:navigationBarColor">@color/colorAccentTeal</item>
<item name="ab_divider_style">@style/AppThemeTeal.ActionBarDivider</item>
</style>
问题:
谁能告诉我我做错了什么以及如何防止增加内存使用量?或者也许有更好的方法可以在运行时改变应用的风格?
提前致谢!
【问题讨论】:
-
在 Android 中泄露活动非常容易。你在使用任何 AsyncTasks 或 Handlers 吗?你有持有上下文的单例吗?
-
如果您只是旋转设备而不调用主题切换代码,内存占用是否也会以同样的无限方式增长?此外,由于您要重新启动同一个 Activity,我想您只需使用
android:launchMode="singleTop"就可以过关,而您不需要Intent.FLAG_ACTIVITY_REORDER_TO_FRONT。这有帮助吗? -
感谢您的快速回复! @CaseyB 我确实在我的代码中使用了 AsyncTasks 和 Handlers,但是为了测试,我评论了所有代码,只留下了
setTheme和setContentView方法。 @theFunkyEngineer 旋转设备会导致同样的情况。感谢您的回答,我尝试创建全新的测试项目。当我使用默认创建的 xml 布局时,重新创建活动内存后会增长,但几次后会返回到初始状态(大约 11mb)。当我将以前的 xml 布局放入新项目时 - 问题又回来了。所以我认为我的布局管理不好。我会用更多信息更新我的问题!
标签: android memory-management memory-leaks out-of-memory android-theme