Я настроил небольшой пример приложения, в котором идея состоит в том, чтобы переходить от одного занятия к другому и изучать потребление памяти, потому что я не совсем понимаю, когда и где освобождается память во время этого процесса.
Идея состоит в том, чтобы создать 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 один раз
Использование памяти после перехода к BlogListActivity несколько раз
Как мы видим, даже после навигации между обоими Activity у нас все еще есть только один объект BlogListActivity в памяти (со связанным с ним содержимым).
Но количество объектов Java и Android увеличивается (строки 2 и 3).