Android проблема с поиском утечки памяти - PullRequest
0 голосов
/ 24 ноября 2011

У меня проблемы с приложением из-за нехватки памяти.Я вполне уверен, что где-то происходит утечка памяти, и я считаю, что я сузил ее до определенного вида деятельности и считаю, что утечка связана с AdMob.

Чтобы проиллюстрировать то, что я вижу, если запустите мое приложение, первое действие занимает около 3 МБ (оно отображает изображение).Когда загружается второе действие, первое не уничтожается, и общее использование кучи увеличивается до ~ 7,8 МБ.После загрузки рекламы AdMob во втором упражнении общий размер кучи достигает примерно 12,5 МБ.

Если я вернусь к первому упражнению, нажав кнопку «Назад», будет вызван метод onDestroy() второго занятия.,Однако объем памяти, используемой моим приложением, не уменьшается совсем.Даже если я вызываю System.gc () явно.Возможно, я ошибаюсь, но разве размер кучи не должен возвращаться к 3Мб?

Что меня еще больше смущает, так это то, что если я оставлю приложение живым и снова открою второе действие, размер кучи только увеличитсяможет быть, на 500 КБ или около того каждый раз, когда я возвращаюсь и четвертый.Как будто что-то поддерживается и используется повторно во втором упражнении, даже если оно было уничтожено.

Я упростил свой код здесь, чтобы посмотреть, не может ли кто-нибудь сказать мне, что я делаю неправильно.Я также взглянул на файлы дампа с помощью MAT, но я не очень уверен в том, что я смотрю, и не нашел большого применения.

Моя первая (по умолчанию) активность

public class FirstActivity extends Activity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, 
                             WindowManager.LayoutParams.FLAG_FULLSCREEN);
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);

        setContentView(R.layout.main);
     }


     public void startSelectionPage(View v){
         Intent intent = new Intent(FirstActivity.this, ImageSelectActivity.class);
         startActivity(intent);
     }
}

main.xml

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:background="@drawable/startpage" >

        <ImageButton
          android:id="@+id/pb"
          android:layout_width="wrap_content"
          android:layout_height="wrap_content"
          android:background="@drawable/playbutton"
          android:onClick="startSelectionPage"          
     />
</RelativeLayout>

ImageSelectActivity

public class ImageSelectActivity extends Activity {
    @Override
    public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
         requestWindowFeature(Window.FEATURE_NO_TITLE);
         getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, 
                             WindowManager.LayoutParams.FLAG_FULLSCREEN);

         setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);

         setContentView(R.layout.selectionpage);    

         ((Gallery) findViewById(R.id.gallery))
         .setAdapter(new ImageAdapter(this.getApplicationContext(), 150));     
    }

     @Override
     public void onDestroy() {
        AdView ad = (AdView) findViewById(R.id.adView);
        ad.destroy();
        super.onDestroy();
     }
 }

 class ImageAdapter extends BaseAdapter {
    private Context myContext;
    private int imageBackground;
    private int galleryHeight;

    private int[] myImageIds = {
                R.drawable.canyonthumb,
                R.drawable.yosemitethumb,
                R.drawable.flowerthumb,
                R.drawable.squirrelthumb

    };

    public ImageAdapter(Context c, int galleryHeight) { 
        this.myContext = c;
        TypedArray ta = c.obtainStyledAttributes(R.styleable.GalleryTheme);
        imageBackground = ta.getResourceId(R.styleable.GalleryTheme_android_galleryItemBackground, 1);
        ta.recycle();
        this.galleryHeight = galleryHeight;
    }

    public int getCount() { return this.myImageIds.length; }
    public Object getItem(int position) { return position; }
    public long getItemId(int position) { return position; }

    public View getView(int position, View convertView, ViewGroup parent) {     
        ImageView imageView = new ImageView(myContext);
        imageView.setScaleType(ImageView.ScaleType.FIT_XY);
        imageView.setLayoutParams(new Gallery.LayoutParams(galleryHeight,galleryHeight));
        imageView.setBackgroundResource(imageBackground);
        imageView.setImageResource(this.myImageIds[position]);
        return imageView;
    }
}

selectionpage.xml

        <ImageView
            android:id="@+id/imageView1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/chooseanimage"/>

        <RelativeLayout
            android:id="@+id/rlayout1"
              android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            >

                    <com.google.ads.AdView android:id="@+id/adView"
                         android:layout_width="wrap_content"
                         android:layout_height="60dp"
                         ads:adUnitId="----"
                         ads:adSize="IAB_BANNER"
                         ads:testDevices="TEST_EMULATOR,---"
                         ads:loadAdOnCreate="true"
                         />

                    <Gallery
                        android:id="@+id/gallery"
                        android:layout_width="fill_parent"
                        android:layout_height="fill_parent"
                        android:layout_below="@id/imageView1"
                        android:layout_above="@+id/adView"
                        />

        </RelativeLayout>   
        </LinearLayout>        

Ответы [ 3 ]

0 голосов
/ 24 ноября 2011

Я не уверен, правильно ли я понял код, но вот что я думаю:

В ImageSelectActivity вы создаете новый объект ImageAdapter. Это анонимный объект, так как вы используете new в вызове setAdapter().

Объект ImageAdapter не будет уничтожен, пока живет ваша деятельность. Вы можете установить для адаптера вашей активности значение NULL в onDestroy()

Очень хорошая запись в блоге о вашей теме: предотвращение утечек памяти

Третий пункт в конце:

Избегайте нестатических внутренних классов в деятельности, если вы не контролируете их жизненный цикл, использовать статический внутренний класс и сделать слабую ссылку к активности внутри. Решением этой проблемы является использование статического внутренний класс с WeakReference на внешний класс, как это сделано в ViewRoot и его внутренний класс W, например

Вот что вы должны делать.

0 голосов
/ 29 ноября 2011

Я не верю, что у меня когда-либо была утечка памяти. Проблема была с GC, который, казалось, позволял объектам оставаться в памяти гораздо дольше, чем я ожидал. Если я попробую код на эмуляторе 16 Мб, GC будет работать гораздо агрессивнее.

Еще одна вещь, которую я не ожидал, это высокий уровень использования памяти AdMob. Добавление рекламы к одному из моих действий привело к использованию ~ 8 МБ кучи.

0 голосов
/ 24 ноября 2011

Проверьте этот вопрос: Управление памятью Android в жизненном цикле активности .Это не совсем тот же вопрос, что и у вас, но ответы содержат информацию, которую, я полагаю, вы ищете.

Так что вместо того, чтобы вводить длинное объяснение связи между памятью, сборщиком мусора и жизненным циклом активностисобираюсь отослать вас к вышеупомянутому вопросу.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...