Android程序运行时出现java.lang.OutOfMemoryError 错误

来源:互联网 发布:网络推广诺一品牌公关 编辑:程序博客网 时间:2024/05/12 14:14

写了一个用Paint和Canvas画图的类,画完之后将所画内容保存到手机sd卡上。

1》代码如下:

package me.linkcube.taku.ui.share;import java.io.File;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;import android.content.res.Resources;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.graphics.Bitmap.Config;import android.os.Environment;import android.util.Log;public class DrawPicPNG {private Bitmap mBitmap;// 画布private Canvas mCanvas;// 画笔--画图片private Paint mPicturePaint;// 画笔--写字private Paint mTextPaint;// 画笔--写运动数据private Paint mDataPaint;public DrawPicPNG() {// TODO Auto-generated constructor stub// 初始化画笔mPicturePaint = new Paint();// 初始化画笔mTextPaint = new Paint();mDataPaint = new Paint();// 设置画笔mTextPaint.setColor(Color.WHITE);// 白色画笔mTextPaint.setTextSize(80.0f);// 设置字体大小// 初始化画笔mDataPaint = new Paint();// 绘制文字mDataPaint.setColor(Color.RED);// 红色画笔mDataPaint.setTextSize(120.0f);// 设置字体大小}/** * @param resources *            :Class for accessing an application's resources. * @param bg_resId *            : 背景图片的资源 ID,如,R.drawable. * @param head_resId *            : 头部图片的资源ID * @param distance *            : 距离,如123.0f * @param timeString *            :时间字符串,如:23:12 * @param cal *            :消耗的卡路里,如:456 * */public void drawBitmap(Resources resources, int bg_resId, int head_resId,float distance, String timeString, int cal) {Bitmap bm_bg = BitmapFactory.decodeResource(resources, bg_resId);// 得到图片的宽、高int bg_width = bm_bg.getWidth();int height_bg = bm_bg.getHeight();// 创建一个你需要尺寸的BitmapmBitmap = Bitmap.createBitmap(bg_width, height_bg, Config.ARGB_8888);// 用这个Bitmap生成一个Canvas,然后canvas就会把内容绘制到上面这个bitmap中mCanvas = new Canvas(mBitmap);// 绘制背景图片mCanvas.drawBitmap(bm_bg, 0.0f, 0.0f, mPicturePaint);// 绘制图片Bitmap bm_head = BitmapFactory.decodeResource(resources, head_resId);// 得到图片的宽、高int width_head = bm_head.getWidth();int head_height = bm_head.getHeight();// 绘制图片--保证其在水平方向居中mCanvas.drawBitmap(bm_head, (bg_width - width_head) / 2, 0.0f,mPicturePaint);// 绘制运动距离文字String distanceTextString = "运动距离:";String distanceDataString = String.valueOf(distance);String distanceScalString = "米";float distanceTextString_width = mTextPaint.measureText(distanceTextString, 0, distanceTextString.length());float distanceDataString_width = mDataPaint.measureText(distanceDataString, 0, distanceDataString.length());float distanceScalString_width = mTextPaint.measureText(distanceScalString, 0, distanceScalString.length());float x_distance = (bg_width - distanceTextString_width- distanceDataString_width - distanceScalString_width) / 2;mCanvas.drawText(distanceTextString, x_distance, head_height + 30,mTextPaint);// 绘制文字mCanvas.drawText(distanceDataString, x_distance+ distanceTextString_width, head_height + 30, mDataPaint);// 绘制文字mCanvas.drawText(distanceScalString, x_distance+ distanceTextString_width + distanceDataString_width,head_height + 30, mTextPaint);// 绘制文字// 绘制运动时间文字String timeTextString = "运动时间:";String timeDataString = String.valueOf(timeString);String timeScalString = "分/秒";float timeTextString_width = mTextPaint.measureText(timeTextString, 0,timeTextString.length());float timeDataString_width = mDataPaint.measureText(timeDataString, 0,timeDataString.length());float timeScalString_width = mTextPaint.measureText(timeScalString, 0,timeScalString.length());float x_time = (bg_width - timeTextString_width - timeDataString_width - timeScalString_width) / 2;mCanvas.drawText(timeTextString, x_time, head_height + 180, mTextPaint);// 绘制文字mCanvas.drawText(timeDataString, x_time + timeTextString_width,head_height + 180, mDataPaint);// 绘制文字mCanvas.drawText(timeScalString, x_time + timeTextString_width+ timeDataString_width, head_height + 180, mTextPaint);// 绘制文字// 绘制消耗卡路里文字String calTextString = "消耗:";String calDataString = String.valueOf(cal);String calScalString = "大卡";float calTextString_width = mTextPaint.measureText(calTextString, 0,calTextString.length());float calDataString_width = mDataPaint.measureText(calDataString, 0,calDataString.length());float calScalString_width = mTextPaint.measureText(calScalString, 0,calScalString.length());float x_cal = (bg_width - calTextString_width - calDataString_width - calScalString_width) / 2;mCanvas.drawText(calTextString, x_cal, head_height + 330, mTextPaint);// 绘制文字mCanvas.drawText(calDataString, x_cal + calTextString_width,head_height + 330, mDataPaint);// 绘制文字mCanvas.drawText(calScalString, x_cal + calTextString_width+ calDataString_width, head_height + 330, mTextPaint);// 绘制文字// 保存绘图mCanvas.save(Canvas.ALL_SAVE_FLAG);mCanvas.restore();savePicPNG();}/** * 保存为本地PNG图片 * */private void savePicPNG() {File file = new File(Environment.getExternalStorageDirectory().getPath() + "/share_pic.png");// 保存到sdcard根目录下,文件名为share_pic.pngLog.i("CXC", Environment.getExternalStorageDirectory().getPath());FileOutputStream fos = null;try {fos = new FileOutputStream(file);mBitmap.compress(Bitmap.CompressFormat.PNG, 50, fos);} catch (FileNotFoundException e) {// TODO Auto-generated catch blocke.printStackTrace();}try {fos.close();} catch (IOException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}
2》当然一定要在Manifest.xml文件中加入相关权限属性

    <!-- 在SDCard中创建与删除文件权限 -->    <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />    <!-- 往SDCard写入数据权限 -->    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

3》在程序中调用此方法

DrawPicPNG picPNG = new DrawPicPNG();picPNG.drawBitmap(getResources(), R.drawable.dashboard_bg,R.drawable.share_head_img, 1234.0f,"22:11",456);

4》运行程序,出现java.lang.OutOfMemoryError 错误

如下图所示:


5》原因及解决方法:

一般android内存比较大,如果出现此问题,则要检查如下两点:
1》》代码质量问题,代码中有易造内存泄露代码
2 》》Android栈空间确实不大,避免多次调用递归。如果无法避免递归 ,那么请在递归函数体内少使用局部变量,及临时变量。

6》本例解决方法--尽量减少局部变量的使用

优化后的代码如下:

/** * @param bg_resId *            : 背景图片的资源 ID,如,R.drawable. *  * @param head_resId *            : 头部图片的资源ID * @param distance *            : 距离,如123.0f * @param timeString *            :时间字符串,如:23:12 * @param cal *            :消耗的卡路里,如:456 * */public void drawBitmap(int bg_resId, int head_resId, float distance,String timeString, int cal) {Bitmap bitmap = BitmapFactory.decodeResource(getResources(), bg_resId);// 得到图片的宽、高int bg_width = bitmap.getWidth();int height_bg = bitmap.getHeight();// 创建一个你需要尺寸的BitmapmBitmap = Bitmap.createBitmap(bg_width, height_bg, Config.ARGB_8888);// 用这个Bitmap生成一个Canvas,然后canvas就会把内容绘制到上面这个bitmap中mCanvas = new Canvas(mBitmap);// 绘制背景图片mCanvas.drawBitmap(bitmap, 0.0f, 0.0f, mTextPaint);// 绘制图片bitmap = BitmapFactory.decodeResource(getResources(), head_resId);// 得到图片的宽、高int head_width = bitmap.getWidth();int head_height = bitmap.getHeight();// 绘制图片--保证其在水平方向居中mCanvas.drawBitmap(bitmap, (bg_width - head_width) / 2, 0.0f,mTextPaint);// 绘制运动距离文字textString = "运动距离:";dataString = String.valueOf(distance);scalString = "米";textString_width = mTextPaint.measureText(textString, 0,textString.length());dataString_width = mDataPaint.measureText(dataString, 0,dataString.length());scalString_width = mTextPaint.measureText(scalString, 0,scalString.length());x = (bg_width - textString_width - dataString_width - scalString_width) / 2;mCanvas.drawText(textString, x, head_height + 30, mTextPaint);// 绘制文字mCanvas.drawText(dataString, x + textString_width, head_height + 30,mDataPaint);// 绘制文字mCanvas.drawText(scalString, x + textString_width + dataString_width,head_height + 30, mTextPaint);// 绘制文字// 绘制运动时间文字textString = "运动时间:";dataString = String.valueOf(timeString);scalString = "分/秒";textString_width = mTextPaint.measureText(textString, 0,textString.length());dataString_width = mDataPaint.measureText(dataString, 0,dataString.length());scalString_width = mTextPaint.measureText(scalString, 0,scalString.length());x = (bg_width - textString_width - dataString_width - scalString_width) / 2;mCanvas.drawText(textString, x, head_height + 180, mTextPaint);// 绘制文字mCanvas.drawText(dataString, x + textString_width, head_height + 180,mDataPaint);// 绘制文字mCanvas.drawText(scalString, x + textString_width + dataString_width,head_height + 180, mTextPaint);// 绘制文字// 绘制消耗卡路里文字textString = "消耗:";dataString = String.valueOf(cal);scalString = "大卡";textString_width = mTextPaint.measureText(textString, 0,textString.length());dataString_width = mDataPaint.measureText(dataString, 0,dataString.length());scalString_width = mTextPaint.measureText(scalString, 0,scalString.length());x = (bg_width - textString_width - dataString_width - scalString_width) / 2;mCanvas.drawText(textString, x, head_height + 330, mTextPaint);// 绘制文字mCanvas.drawText(dataString, x + textString_width, head_height + 330,mDataPaint);// 绘制文字mCanvas.drawText(scalString, x + textString_width + dataString_width,head_height + 330, mTextPaint);// 绘制文字// 保存绘图mCanvas.save(Canvas.ALL_SAVE_FLAG);mCanvas.restore();savePicPNG();}

当然,本程序还有很多要改进的地方。如,画图片时,图片的解析方式等。




0 0
原创粉丝点击