开发者

Understanding memory management when navigating inside Activities

I have setup a little example application where the idea is to navigate from one Activity to another and to study Memory consumption because I don't really understand when/where memory is released during this process.

Idea is to create an Activity which consume quite a lot of memory to see if memory is released correctly when we leave it before recreating it.

  • A HomeActivity only composed of a Button that call a BlogListActivity when button is clicked.
  • BlogListActivity is a ListActivity that contain BlogPost objects. This BlogPost contains a Bitmap in order to use some memory.

List of BlogPost is created dynamically in the onCreate method of BlogListActivity and then passed to an Adapter to display each PostBlog object in row of my ListView.

On an emulator with Android 2.3.3 and 128Mo of memory, I manage to move from HomeActivity to BlogListActivity and then come back to HomeActivity two times. On the third try, I get an OutOfMemoryError from BitmapFactory.

This mean I have a Memory Leak: objects that are not used anymore but still have a reference on it so they are not released. But I don't where I do it wrong.

Can someone help me finding it.

Thanks in advance for your help.

Bertrand

Link to complete source code and Eclipse project

Here is an extract of the code we are interested in

HomeActivity source code

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 source code

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 source code

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 source code

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>
<开发者_StackOverflow/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>

I have studied memory usage with DDMS + MAT. Here are screenshots of what I see in MAT for the com.webcontentlistview I create: Memory usage after navigating to BlogListActivity one time

Understanding memory management when navigating inside Activities

Memory usage after navigatin to BlogListActivity several times

Understanding memory management when navigating inside Activities

As we can see, even after navigating between both Activity, we still have only one BlogListActivity object in memory (with it's associated content). But numbers of java and android objects are increasing (lines 2 and 3).


Could it be that the garbage collector simply does not have time to clean your data before you launch the activity again? How quickly did you do the test? Does it always crash, even if you take some time between starting BlogListActivity? Maybe try to run System.gc() each time the app returns to HomeActivity and see if the crashes resume.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜