我的代码在方向更改时出现大量内存泄漏。旋转手机一到两次后堆已满。我试图追踪泄漏两天,但没有成功。
该应用程序使用SDK 15(分14)。
MainActivity
显示带有列表导航(NAVIGATION_MODE_LIST
)的ActionBar。导航微调器会替换显示的片段。
代码有效。
ListNavigationItem
,其中包含实例化片段所需的信息:
public class ListNavigationItem
{
public final String fragmentClass;
public final String title; // Used as fragment tag and as title
public ListNavigationItem(String fragmentClass, String title)
{
this.fragmentClass = fragmentClass;
this.title = title;
}
@Override
public String toString()
{
return title;
}
}
最后我的(简体)MainActivity
:
public class MainActivity extends Activity implements OnNavigationListener
{
private MyApplication app;
private ArrayAdapter<ListNavigationItem> adapter;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
app = (MyApplication) getApplicationContext();
ActionBar actionBar = getActionBar();
actionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);
actionBar.setDisplayShowTitleEnabled(false);
actionBar.setDisplayShowHomeEnabled(false);
adapter = new ArrayAdapter<ListNavigationItem>(this, android.R.layout.simple_spinner_dropdown_item);
adapter.add(new ListNavigationItem(FirstFragment.class.getName(), "First"));
adapter.add(new ListNavigationItem(SecondFragment.class.getName(), "Second"));
actionBar.setListNavigationCallbacks(adapter, this);
}
public boolean onNavigationItemSelected(int itemPosition, long itemId)
{
ListNavigationItem item = adapter.getItem(itemPosition);
if (item == null)
return false;
Fragment f = getFragmentManager().findFragmentByTag(item.title);
if (f == null)
f = Fragment.instantiate(this, item.fragmentClass);
else if (f.isAdded())
return true;
FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction();
fragmentTransaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
fragmentTransaction.replace(R.id.main_content, f, item.title);
fragmentTransaction.commit();
return true;
}
@Override
protected void onDestroy()
{
adapter = null; // Do I need this?
app = null;
super.onDestroy();
}
}
清单:
<?xml version="1.0" encoding="utf-8"?>
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="at.company.app"
android:versionCode="1"
android:versionName="1.0">
<uses-sdk android:minSdkVersion="14" />
<uses-sdk android:targetSdkVersion="15" />
<application
android:name=".Application"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name">
<activity
android:name=".MainActivity"
android:label="@string/app_name">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
MAT堆分析表明类android.content.res.Resources
占可用内存的57%,而android.graphics.Bitmap
占12%。但是,我的片段只包含一个简单的TextView
。
MAT直方图显示MainActivity
有4个对象(实例,我假设?)。此外,logcat显示在更改方向(GC_CONCURRENT)后,堆经常被清空。
官方开发指南不鼓励使用android:configChanges="orientation"
。 (Source)
我对Java和Android平台相对较新,我将不胜感激。
答案 0 :(得分:0)
这将取决于你的清单配置,但测试你可以完成onConfigurationChanged ..否则它只会创建一个新的活动而不会破坏旧的活动..
答案 1 :(得分:0)
我不知道为什么,如何,或者这是否是我的问题。但是,当我删除片段事务的setTransition时,我似乎停止获取“增长堆”输出。试试吧?
答案 2 :(得分:0)
内存泄漏的常见原因是在上下文引用中引用Activity
而不是Application
。使用this
(例如adapter = new ArrayAdapter<ListNavigationItem>(this
)可能导致内存泄漏,如question中所述,因此请尝试将其替换为getApplicationContext()
以引用Application
而不是上下文。