Android 在活动内部导航时了解内存管理
我已经建立了一个小的示例应用程序,其中的想法是从一个活动导航到另一个活动,并研究内存消耗,因为我真的不知道在这个过程中内存何时/何处被释放 这个想法是创建一个消耗大量内存的活动,以查看在重新创建之前,当我们离开它时,内存是否被正确释放 HomeActivity仅由一个按钮组成,该按钮在单击按钮时调用BlogListActivity。 BlogListActivity是包含BlogPost对象的ListActivity。此博客文章包含一个位图以使用一些内存。 BlogPost列表是在BlogListActivity的onCreate方法中动态创建的,然后传递给适配器以在my ListView的行中显示每个PostBlog对象 在Android 2.3.3和128Mo内存的模拟器上,我设法从HomeActivity移动到BlogListActivity,然后两次返回HomeActivity。在第三次尝试中,我从BitmapFactory得到一个OutOfMemoryError 这意味着我有一个内存泄漏:不再使用但仍有引用的对象,因此它们不会被释放。但我不知道我哪里做错了 有人能帮我找到它吗 提前感谢你的帮助 伯特兰 下面是我们感兴趣的代码摘录 HomeActivity源代码Android 在活动内部导航时了解内存管理,android,memory-management,android-activity,Android,Memory Management,Android Activity,我已经建立了一个小的示例应用程序,其中的想法是从一个活动导航到另一个活动,并研究内存消耗,因为我真的不知道在这个过程中内存何时/何处被释放 这个想法是创建一个消耗大量内存的活动,以查看在重新创建之前,当我们离开它时,内存是否被正确释放 HomeActivity仅由一个按钮组成,该按钮在单击按钮时调用BlogListActivity。 BlogListActivity是包含BlogPost对象的ListActivity。此博客文章包含一个位图以使用一些内存。 BlogPost列表是在BlogLis
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));
}
}
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));
}
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;
}
}
public class BlogPost {
public String title;
public String author;
public Date date;
public String imageURL;
public Bitmap image;
}
BlogListActivity源代码
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));
}
}
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));
}
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;
}
}
public class BlogPost {
public String title;
public String author;
public Date date;
public String imageURL;
public Bitmap image;
}
活动列表布局
<?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布局
<?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>
家庭活动布局:
<?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后的内存使用情况
正如我们所看到的,即使在两个活动之间导航,内存中仍然只有一个BlogListActivity对象及其相关内容。
但是java和android对象的数量正在增加第2行和第3行。是否垃圾收集器在您再次启动活动之前根本没有时间清理您的数据?你做测试的速度有多快?它是否总是崩溃,即使您在启动BlogListActivity之间需要一些时间?每次应用程序返回HomeActivity时,可能尝试运行System.gc,看看崩溃是否会继续。谢谢您的建议,但即使在HomeActivity的onCreate方法中调用System.gc也不能解决问题。onCreate只运行一次,请尝试在onResume上运行它,以便它在您启动BlogListActivity之间运行。还有,我的其他问题:在启动BlogListActivity之间等待几秒钟是否有帮助,然后内存可能有机会被垃圾收集。GC不会立即工作,它会在内存中迭代以查找要清理的内容。1我每次按下设备的“后退”按钮时都会输入HomeActivity.onCreate方法,对我来说这是正常行为,不是吗?。2即使在onResume方法中执行System.gc或/或在从一个活动移动到另一个活动之前等待5秒,我也会从BitMapFactory中得到OutOfMemory错误返回到活动时输入onCreate是不正常的-您应该看到onRestart、onStart和onResume。