Понимание управления памятью при навигации внутри Activity - PullRequest
0 голосов
/ 18 марта 2011

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

Идея состоит в том, чтобы создать Activity, которая потребляет довольно много памяти, чтобы увидеть, правильно ли освобождается память, когда мы покидаем ее, прежде чем воссоздавать ее.

  • HomeActivity состоит только из кнопки, которая вызывает BlogListActivity при нажатии кнопки.
  • BlogListActivity - это ListActivity, который содержит объекты BlogPost. Этот BlogPost содержит растровое изображение для использования некоторой памяти.

Список BlogPost создается динамически в методе onCreate BlogListActivity, а затем передается адаптеру для отображения каждого объекта PostBlog в строке моего ListView.

В эмуляторе с Android 2.3.3 и 128Мо памяти мне удается перейти от HomeActivity к BlogListActivity, а затем дважды вернуться в HomeActivity. С третьей попытки я получаю OutOfMemoryError от BitmapFactory.

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

Может ли кто-нибудь помочь мне найти его.

Заранее спасибо за помощь.

Bertrand

Ссылка на полный исходный код и проект Eclipse

Вот фрагмент кода, который нас интересует

Исходный код HomeActivity

public class HomeActivity extends Activity {
   @Override
   public void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
      setContentView(R.layout.activity_home);
   }

   public void onSecondActivityClick(View v) {
      startActivity(new Intent(this, BlogListActivity.class));
   }   
}

Исходный код BlogListActivity

public class BlogListActivity extends ListActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_bloglist);

    List<BlogPost> items = new ArrayList<BlogPost>();
    Bitmap bmp = BitmapFactory.decodeResource(getResources(), R.drawable.mn);
    for (int i = 0; i < 5; i++) {
        BlogPost post = new BlogPost();
        post.author = String.format("Author%d", i);
        post.title = String.format("Title%d", i);
        post.date = new Date();
        post.imageURL = "https://si3.twimg.com/profile_images/1143791319/MN_BLEU.png";
        post.image = bmp;
        post.image = BitmapFactory.decodeResource(getResources(), R.drawable.mn);
        items.add(post);
    }
    setListAdapter(new LazyArrayAdapter(this, R.layout.listitem_blog, items));
}

}

Исходный код LazyArrayAdapter

public class LazyArrayAdapter extends ArrayAdapter<BlogPost> {

   public LazyArrayAdapter(Context context, int textViewResourceId, List<BlogPost> objects) {
      super(context, textViewResourceId, objects);
   }

   @Override
   public View getView(int index, View view, ViewGroup parent) {
      LayoutInflater inflater = LayoutInflater.from(parent.getContext());
      if (view == null) {
         view = inflater.inflate(R.layout.listitem_blog, parent, false);
      }

      TextView title = (TextView)view.findViewById(R.id.listitemblog_title);
      TextView date = (TextView)view.findViewById(R.id.listitemblog_date);
      ImageView icon = (ImageView)view.findViewById(R.id.listitemblog_icon);
      BlogPost post = this.getItem(index);

      title.setText(post.title);
      date.setText(new SimpleDateFormat().format(post.date));
      icon.setImageBitmap(post.image);
      return view;
   }
}

Исходный код BlogPost

public class BlogPost {
    public String   title;
    public String   author;
    public Date     date;   
    public String   imageURL;
    public Bitmap   image;
}

Activity_bloglist Layout

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
   xmlns:android="http://schemas.android.com/apk/res/android"
   android:layout_width="fill_parent"
   android:layout_height="fill_parent">
      <ListView 
          android:layout_width="fill_parent"
          android:layout_height="fill_parent"     
          android:id="@android:id/list">
      </ListView>
</LinearLayout>

ListItemBlog Layout

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
   xmlns:android="http://schemas.android.com/apk/res/android"
   android:weightSum="100"
   android:layout_width="fill_parent"
   android:layout_height="fill_parent">
      <LinearLayout android:layout_width="0px" android:layout_weight="70"
         android:id="@+id/linearLayout2"
         android:orientation="vertical"
         android:layout_height="fill_parent">

         <TextView android:id="@+id/listitemblog_title"
               android:layout_width="wrap_content" 
               android:text="TextView" 
               android:textStyle="bold" 
               android:layout_height="wrap_content">
         </TextView>
         <TextView 
               android:id="@+id/listitemblog_date"
               android:layout_width="wrap_content"  
               android:text="TextView" 
               android:layout_height="wrap_content"
               android:textStyle="bold">
            </TextView>
     </LinearLayout>
<ImageView 
        android:id="@+id/listitemblog_icon"
        android:layout_width="0px" 
        android:scaleType="centerInside" 
        android:layout_weight="30" 
        android:src="@drawable/icon"
        android:layout_height="fill_parent"/>
</LinearLayout>

HomeActivity layout:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
   android:orientation="vertical"
   android:layout_width="fill_parent"
   android:layout_height="fill_parent">
   <Button 
      android:layout_height="wrap_content" 
      android:onClick="onSecondActivityClick" 
      android:layout_width="wrap_content" 
      android:id="@+id/button1" 
      android:text="Button">
   </Button>
</LinearLayout>

Я изучал использование памяти с помощью DDMS + MAT. Вот скриншоты того, что я вижу в MAT для создаваемого com.webcontentlistview: Использование памяти после перехода на BlogListActivity один раз Memory usage after navigating to BlogListActivity one time

Использование памяти после перехода к BlogListActivity несколько раз Memory usage after navigatin to BlogListActivity several times

Как мы видим, даже после навигации между обоими Activity у нас все еще есть только один объект BlogListActivity в памяти (со связанным с ним содержимым). Но количество объектов Java и Android увеличивается (строки 2 и 3).

1 Ответ

0 голосов
/ 18 марта 2011

Может быть, сборщик мусора просто не успевает очистить ваши данные, прежде чем вы снова запустите действие?Как быстро вы сделали тест?Всегда ли происходит сбой, даже если у вас есть время между запуском BlogListActivity?Возможно, попробуйте запустить System.gc () каждый раз, когда приложение возвращается в HomeActivity, и посмотрите, возобновляются ли сбои.

...