内存溢出之Bitmap
可以说出现OutOfMemory问题的绝大多数人,都是因为Bitmap的问题。因为Bitmap占用的内存实在是太多了,它是一个“超级大胖子”,特别是分辨率大的图片,如果要显示多张那问题就更显著了。
如何解决Bitmap带给我们的内存问题?
第一、及时销毁。
虽然,系统能够确认Bitmap分配的内存最终会被销毁,但是由于它占用的内存过多,所以很可能会超过java堆的限制。因此,在用完Bitmap时,要及时的recycle掉。recycle并不能确定立即就会将Bitmap释放掉,但是会给虚拟机一个暗示:“该图片可以释放了”。所以Bitmap对象在不使用时,我们应该先调用recycle()释放内存,然后才它设置为null. 虽然recycle()从源码上看,调用它应该能立即释放Bitmap的主要内存,但是测试结果显示它并没能立即释放内存。
if(!bitmap.isRecycled()){
bitmap.recycle();
bitmap = null;
}
第二、设置一定的采样率。
手机就那么屁大的屏幕,所以有时候我们要显示的区域很小,没有必要将整个图片都加载出来,而只需要记载一个缩小过的图片,这时候可以设置一定的采样率,那么就可以大大减小占用的内存。如下面的代码:
public ImageView iv ;
public void example() {
BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 2;// 图片宽高都为原来的二分之一,即图片为原来的四分之一。数值越大图片越模糊.你懂的
//Uri u = Uri.parse( "content://media/internal/audio/media/81" );
// Bitmap bitmap = BitmapFactory.decodeStream(getContentResolver().openInputStream(Uri.parse(uriString)), null, options);
Bitmap bitmap = BitmapFactory.decodeResource(getResources(),
R.drawable.ic_launcher, options);
iv.setImageBitmap(bitmap);
}
第三、巧妙的运用软引用(SoftRefrence)
有些时候,我们使用Bitmap后没有保留对它的引用,因此就无法调用Recycle函数。这时候巧妙的运用软引用,可以使Bitmap在内存快不足时得到有效的释放。
内存溢出之Adapter
构造 Adapter时,没有使用缓存的 convertView
以构造ListView的 BaseAdapter 为例,在BaseAdapter 中提共了方public View getView(int position, View convertView, ViewGroup pare来向ListView提供每一个item所需要的view对象。初始时ListBaseAdapter 中根据当前的屏幕布局实例化一定数量的view对象,同些view对象缓存起来。当向上滚动ListView时,原先位于最上面的象会被回收,然后被用来构造新出现的最下面的list item。这个构造过程方法完成的,getView()的第二个形参
View convertView就是被缓存起view对象(初始化时缓存中没有view对象则convertView是null)。
由此可以看出,如果我们不去使用convertView,而是每次都在getView()中重新实例化一个View对象的话,即浪费时间,也造成内存垃圾,给垃圾回收增加压力,如果垃圾回收来不及的话,虚拟机将不得不给该应用进程分配更多的内存,造成不必要的内存开支。构造 Adapter时,没有使用缓存的 convertView
以构造ListView的 BaseAdapter 为例,在BaseAdapter 中提共了方法:
public View getView(int position, View convertView, ViewGroup parent) 来向ListView提供每一个item所需要的view对象。初始时ListView会从BaseAdapter 中根据当前的屏幕布局实例化一定数量的view对象,同时ListView会将这些view对象缓存起来。当向上滚动ListView时,原先位于最上面的list item的view对象会被回收,然后被用来构造新出现的最下面的list item。这个构造过程就是由getView()方法完成的,getView()的第二个形参
View convertView就是被缓存起来的list item的view对象(初始化时缓存中没有view对象则convertView是null)。
所以综合以上的理论,写了一个小例子,表达一下:
/**
*
******************************************
* @author 老牛比
* 文件名称 : ExampleAdapter.java
* 创建时间 : 2012-10-1 下午11:11:28
* 文件描述 : 优化小例子
******************************************
*/
public class ExampleAdapter extends BaseAdapter {
private ArrayList<SoftReference<Bitmap>> mBitmaps = new ArrayList<SoftReference<Bitmap>>();
private ArrayList<Object> mValues;
private LayoutInflater mInflater;
public ExampleAdapter(ArrayList<SoftReference<Bitmap>> mBitmaps,
ArrayList<Object> mValues, Context mContext,
LayoutInflater mInflater) {
super();
this.mValues = mValues;
this.mInflater = (LayoutInflater) mContext
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
public int getCount() {
return mValues.size();
}
public Object getItem(int position) {
return mValues.get(position);
}
public long getItemId(int position) {
return position;
}
public View getView(int position, View convertView, ViewGroup parent) {
ViewHolder holder;
Bitmap bitmap = BitmapFactory.decodeFile(mValues.get(position).XXX);
mBitmaps.add(new SoftReference<Bitmap>(bitmap)); // 此处加入ArrayList
if (convertView == null) {
convertView = mInflater.inflate(R.layout.example, false);
holder = new ViewHolder();
holder.text = (TextView) convertView.findViewById(R.id.text);
holder.icon = (ImageView) convertView.findViewById(R.id.icon);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
holder.text.setText("xxx");
holder.icon.setImageBitmap(bitmap);
return convertView;
}
/**
*
******************************************
* @author 老牛比
* 文件名称 : ViewHolder.java
* 创建时间 : 2012-10-1 下午10:35:25
* 文件描述 : 使用 ViewHolder 模式, 效率再提高 50%
******************************************
*/
class ViewHolder {
TextView text;
ImageView icon;
}
}
内存溢出之Cursor
Cursor是Android查询数据后得到的一个管理数据集合的类,正常情况下,操作小数据查询时不会有内存问题,而且虚拟机能够保证Cusor最终会被释放掉。然而如果Cursor的数据量特别大,应该保证Cursor占用的内存被及时的释放掉,而不是等待GC来处理。并且Android 文档中提倡开发者手动的关闭Cursor。
所以我们最好这样使用Cursor:
public void example() {
Cursor mCursor = null;
try {
mCursor = mContext.getContentResolver().query(uri, null, null,
null, null);
if (mCursor != null) {
mCursor.moveToFirst();
// TODO:do something
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (mCursor != null) {
mCursor.close();
}
}
}
但在CursorAdapter中应用的情况下,必须注意,CursorAdapter在Acivity结束时并没有自动的将Cursor关闭掉,因此,你需要在onDestroy函数中,手动关闭:
@Override
protected void onDestroy() {
if (mAdapter != null && mAdapter.getCurosr() != null) {
mAdapter.getCursor().close();
}
super.onDestroy();
}
分享到:
相关推荐
以下是对Android防止内存溢出的深入浅析: 1. **Android内存管理机制** - **Dalvik/ART虚拟机**:Android系统使用Dalvik或ART虚拟机执行应用程序,它们都有自己的内存管理策略。 - **堆内存**:Java对象主要存储...
在Android开发中,防止内存溢出是一个至关重要的任务,因为Android设备的内存资源相对有限,尤其是在Dalvik虚拟机中,其最大堆大小通常只有16MB。本文将深入探讨Android平台上的内存管理机制,以及如何避免内存泄露...
本文将深入浅析如何在Android环境中预防和处理内存溢出问题。 首先,我们需要了解Android的内存模型。Android系统采用Dalvik或ART虚拟机来运行应用程序,每个应用都有自己的内存空间,当这个空间被耗尽时,就会触发...
本篇文章将深入浅析Android源码中的内存管理机制,以及如何预防和处理内存溢出问题。 首先,我们需要理解Android应用的内存结构。Android系统的内存分为堆(Heap)和栈(Stack)。栈主要存放方法的局部变量,而堆则...
本资源"Android应用源码之防止内存溢出浅析"旨在深入探讨如何通过源码分析来避免这种问题。 一、Android内存管理基础 Android系统采用Dalvik虚拟机(在Android 5.0之后改为ART)执行应用代码,其内存管理基于垃圾...
综上所述,防止Android应用内存溢出需要从多个层面进行考虑和优化,包括但不限于理解GC机制、避免内存泄漏、合理使用资源、优化代码结构以及使用专业工具进行分析和调试。只有这样,才能确保应用在运行过程中保持...
这个"Android应用源码之防止内存溢出浅析"的压缩包可能包含了示例代码,通过阅读和分析这些代码,你可以理解以上策略如何在实际项目中应用。例如,查看图片加载部分,是否使用了合适的解码选项;检查Activity的生命...
本资料"应用源码之防止内存溢出浅析"旨在深入探讨Android应用中的内存优化,帮助开发者避免因不当使用内存导致的应用崩溃。以下是根据标题、描述和标签提炼的相关知识点: 1. **Java内存模型**:Java内存分为堆内存...
二、内存泄漏分析 1. 静态变量:静态变量生命周期长,如果持有Activity或Context的引用,可能导致Activity无法被销毁,占用内存。 2. 单例模式:不正确的单例实现可能导致全局持有大量资源,阻碍GC回收。 3. ...
在Android编程中,内存溢出(Memory Leak)是一个常见的问题,尤其对于有限的移动设备资源而言,内存管理显得尤为重要。Android的Dalvik虚拟机虽然在内存管理上与Java虚拟机有相似之处,但由于其内存限制(通常是16...
4. 利用Android提供的内存分析工具:如Memory Profiler,可以帮助我们实时监控应用的内存使用情况,找出潜在的内存泄漏问题。 5. 使用 LeakCanary:这是一个开源库,可以帮助检测应用中的内存泄露,提供详细的泄露...