Утечка памяти в Android при использовании ActionBar и Spinner - PullRequest
0 голосов
/ 14 февраля 2012

Мой код имеет значительную утечку памяти при изменении ориентации.Куча полна после поворота телефона один или два раза.Я пытался отследить утечку в течение двух дней безуспешно.

Приложение использует SDK 15 (мин. 14).

MainActivity показывает панель действий с навигацией по списку (NAVIGATION_MODE_LIST),Навигация по счетчику заменяет показанный фрагмент.

Код работает.

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 показывает, что существует 4 объекта (экземпляры, я полагаю?) С MainActivity.Кроме того, logcat показывает, что куча часто очищается после изменения ориентации (GC_CONCURRENT).

Официальное руководство разработчика не рекомендует использовать android:configChanges="orientation".( Source )

Я относительно новичок в Java и платформе Android, и я был бы признателен за любую помощь.

Ответы [ 3 ]

0 голосов
/ 22 августа 2012

Я не знаю почему, как или если это моя проблема.Но я, кажется, перестал получать вывод «куча роста», когда я удалил setTransition для транзакции фрагмента.Попробуйте это?

0 голосов
/ 04 октября 2012

Распространенной причиной утечек памяти является ссылка Activity вместо Application в контекстных ссылках.Использование this (например, adapter = new ArrayAdapter<ListNavigationItem>(this) может вызвать утечку памяти, как объяснено в этом вопросе , поэтому попробуйте заменить ее на getApplicationContext() для ссылки на контекст Application.

0 голосов
/ 14 февраля 2012

Это будет зависеть от вашей конфигурации манифеста, но для проверки вы могли бы завершить onConfigurationChanged .. в противном случае он просто создаст новое действие, не разрушая старого потенциально ..

...