`
jiav_net
  • 浏览: 110222 次
文章分类
社区版块
存档分类
最新评论

Android 内存浅析【泄漏、溢出】【二】

 
阅读更多
内存溢出之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防止内存溢出浅析.zip

    以下是对Android防止内存溢出的深入浅析: 1. **Android内存管理机制** - **Dalvik/ART虚拟机**:Android系统使用Dalvik或ART虚拟机执行应用程序,它们都有自己的内存管理策略。 - **堆内存**:Java对象主要存储...

    Android防止内存溢出浅析

    在Android开发中,防止内存溢出是一个至关重要的任务,因为Android设备的内存资源相对有限,尤其是在Dalvik虚拟机中,其最大堆大小通常只有16MB。本文将深入探讨Android平台上的内存管理机制,以及如何避免内存泄露...

    基于Android防止内存溢出浅析

    本文将深入浅析如何在Android环境中预防和处理内存溢出问题。 首先,我们需要了解Android的内存模型。Android系统采用Dalvik或ART虚拟机来运行应用程序,每个应用都有自己的内存空间,当这个空间被耗尽时,就会触发...

    安卓Android源码——防止内存溢出浅析.zip

    本篇文章将深入浅析Android源码中的内存管理机制,以及如何预防和处理内存溢出问题。 首先,我们需要理解Android应用的内存结构。Android系统的内存分为堆(Heap)和栈(Stack)。栈主要存放方法的局部变量,而堆则...

    Android应用源码之防止内存溢出浅析.zip

    本资源"Android应用源码之防止内存溢出浅析"旨在深入探讨如何通过源码分析来避免这种问题。 一、Android内存管理基础 Android系统采用Dalvik虚拟机(在Android 5.0之后改为ART)执行应用代码,其内存管理基于垃圾...

    防止内存溢出浅析

    综上所述,防止Android应用内存溢出需要从多个层面进行考虑和优化,包括但不限于理解GC机制、避免内存泄漏、合理使用资源、优化代码结构以及使用专业工具进行分析和调试。只有这样,才能确保应用在运行过程中保持...

    Android应用源码之防止内存溢出浅析-IT计算机-毕业设计.zip

    这个"Android应用源码之防止内存溢出浅析"的压缩包可能包含了示例代码,通过阅读和分析这些代码,你可以理解以上策略如何在实际项目中应用。例如,查看图片加载部分,是否使用了合适的解码选项;检查Activity的生命...

    应用源码之防止内存溢出浅析.zip

    本资料"应用源码之防止内存溢出浅析"旨在深入探讨Android应用中的内存优化,帮助开发者避免因不当使用内存导致的应用崩溃。以下是根据标题、描述和标签提炼的相关知识点: 1. **Java内存模型**:Java内存分为堆内存...

    安卓开发-防止内存溢出浅析.zip

    二、内存泄漏分析 1. 静态变量:静态变量生命周期长,如果持有Activity或Context的引用,可能导致Activity无法被销毁,占用内存。 2. 单例模式:不正确的单例实现可能导致全局持有大量资源,阻碍GC回收。 3. ...

    Android编程内存溢出与防范方法浅析

    在Android编程中,内存溢出(Memory Leak)是一个常见的问题,尤其对于有限的移动设备资源而言,内存管理显得尤为重要。Android的Dalvik虚拟机虽然在内存管理上与Java虚拟机有相似之处,但由于其内存限制(通常是16...

    浅析安卓(Android)的性能优化

    4. 利用Android提供的内存分析工具:如Memory Profiler,可以帮助我们实时监控应用的内存使用情况,找出潜在的内存泄漏问题。 5. 使用 LeakCanary:这是一个开源库,可以帮助检测应用中的内存泄露,提供详细的泄露...

Global site tag (gtag.js) - Google Analytics