最近做一个android 的应用程序 总是出现内存高 和cpu高的问题困扰了好多天。

下面为自己从网上总结的和自己找到的问题。

1. WebView  控件:

使用了 WebView 控件一定要注意清理缓存  destroy() 方法,但之前必须调用 removeAllViews() 要不然有时出错

1 myWebView.removeAllViews();
2 myWebView.destroy();

2.线程

在退出活动窗口时一定要注意开启的线程是否已经关闭,可以在debug查看线程的开启情况。

如果只是刷新Ui线程 建议不用线程可以使用 Handler 来刷新 方法如下。这种方法只能做简单的操作,复杂操作建议使用线程。

01 private Handler
_ui_handler = 
new Handler()
{
02  
03     @Override
04     public void handleMessage(Message
msg) {
05  
06     switch (msg.what)
{
07         case 0://下面你可以写你需要处理的代码
08                 _ui_handler
.sendEmptyMessageDelayed(
0,1000)//1000
为延时发送的时间 单位是毫秒
09         break;
10         }
11     }
12 }

3 sqlite

使用sqlite是一定要注意 关闭当前指针 和数据库连接

下面为注意内存溢出的问题

http://rayleeya.iteye.com/blog/727074

各位兄弟姐妹,Java开发中的内存泄露的问题经常会给我们带来很多烦恼。特别是对一些新手,如果平时不注意一些细节问题,最后很可能会导致很严重的后果。

在Android中的Java开发也同样会有这样的问题。附件中的pdf整理了一些关于Android中的Java开发,在内存使用方面需要注意的一些问题,希望能够对大家有所帮助。

接下篇: [Android] 内存泄漏调试经验分享 (二) http://rayleeya.iteye.com/blog/755657

Android 内存泄漏调试

Made by 李文栋

liwd@thunderst.com | rayleeya@gmail.com

2010-07-25  Friday

一、概述 1

二、Android(Java)中常见的容易引起内存泄漏的不良代码 1

(一) 查询数据库没有关闭游标 2

(二) 构造Adapter时,没有使用缓存的 convertView 3

(三) Bitmap对象不在使用时调用recycle()释放内存 4

(四) 释放对象的引用 4

(五) 其他 5

三、内存监测工具 DDMS --> Heap 5

四、内存分析工具 MAT(Memory Analyzer Tool) 7

(一) 生成.hprof文件 7

(二) 使用MAT导入.hprof文件 8

(三) 使用MAT的视图工具分析内存 8

一、概述

Java编程中经常容易被忽视,但本身又十分重要的一个问题就是内存使用的问题。Android应用主要使用Java语言编写,因此这个问题也同样会在Android开发中出现。本文不对Java编程问题做探讨,而是对于在Android中,特别是应用开发中的此类问题进行整理。

由于作者接触Android时间并不是很长,因此如有叙述不当之处,欢迎指正。

二、Android(Java)中常见的容易引起内存泄漏的不良代码

Android主要应用在嵌入式设备当中,而嵌入式设备由于一些众所周知的条件限制,通常都不会有很高的配置,特别是内存是比较有限的。如果我们编写的代码当中有太多的对内存使用不当的地方,难免会使得我们的设备运行缓慢,甚至是死机。为了能够使得Android应用程序安全且快速的运行,Android的每个应用程序都会使用一个专有的Dalvik虚拟机实例来运行,它是由Zygote服务进程孵化出来的,也就是说每个应用程序都是在属于自己的进程中运行的。一方面,如果程序在运行过程中出现了内存泄漏的问题,仅仅会使得自己的进程被kill掉,而不会影响其他进程(如果是system_process等系统进程出问题的话,则会引起系统重启)。另一方面Android为不同类型的进程分配了不同的内存使用上限,如果应用进程使用的内存超过了这个上限,则会被系统视为内存泄漏,从而被kill掉。Android为应用进程分配的内存上限如下所示:

位置: /ANDROID_SOURCE/system/core/rootdir/init.rc 部分脚本

# Define the oom_adj values for the classes of processes that can be

# killed by the kernel.  These are used in ActivityManagerService.

setprop ro.FOREGROUND_APP_ADJ 0

setprop ro.VISIBLE_APP_ADJ 1

setprop ro.SECONDARY_SERVER_ADJ 2

setprop ro.BACKUP_APP_ADJ 2

setprop ro.HOME_APP_ADJ 4

setprop ro.HIDDEN_APP_MIN_ADJ 7

setprop ro.CONTENT_PROVIDER_ADJ 14

setprop ro.EMPTY_APP_ADJ 15

# Define the memory thresholds at which the above process classes will

# be killed.  These numbers are in pages (4k).

setprop ro.FOREGROUND_APP_MEM 1536

setprop ro.VISIBLE_APP_MEM 2048

setprop ro.SECONDARY_SERVER_MEM 4096

setprop ro.BACKUP_APP_MEM 4096

setprop ro.HOME_APP_MEM 4096

setprop ro.HIDDEN_APP_MEM 5120

setprop ro.CONTENT_PROVIDER_MEM 5632

setprop ro.EMPTY_APP_MEM 6144

# Write value must be consistent with the above properties.

# Note that the driver only supports 6 slots, so we have HOME_APP at the

# same memory level as services.

write /sys/module/lowmemorykiller/parameters/adj 0,1,2,7,14,15

write /proc/sys/vm/overcommit_memory 1

write /proc/sys/vm/min_free_order_shift 4

write /sys/module/lowmemorykiller/parameters/minfree 1536,2048,4096,5120,5632,6144

# Set init its forked children's oom_adj.

write /proc/1/oom_adj -16

正因为我们的应用程序能够使用的内存有限,所以在编写代码的时候需要特别注意内存使用问题。如下是一些常见的内存使用不当的情况。

(一) 查询数据库没有关闭游标

描述:

程序中经常会进行查询数据库的操作,但是经常会有使用完毕Cursor后没有关闭的情况。如果我们的查询结果集比较小,对内存的消耗不容易被发现,只有在常时间大量操作的情况下才会复现内存问题,这样就会给以后的测试和问题排查带来困难和风险。

示例代码:

Cursor cursor = getContentResolver().query(uri ...);

if (cursor.moveToNext()) {

... ...

}

修正示例代码:

Cursor cursor = null;

try {

cursor = getContentResolver().query(uri ...);

if (cursor != null && cursor.moveToNext()) {

... ...

}

} finally {

if (cursor != null) {

try {

cursor.close();

} catch (Exception e) {

//ignore this

}

}

}

(二) 构造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)。

由此可以看出,如果我们不去使用convertView,而是每次都在getView()中重新实例化一个View对象的话,即浪费资源也浪费时间,也会使得内存占用越来越大。ListView回收list item的view对象的过程可以查看:

android.widget.AbsListView.java --> void addScrapView(View scrap) 方法。

示例代码:

public View getView(int position, View convertView, ViewGroup parent) {

View view = new Xxx(...);

... ...

return view;

}

修正示例代码:

public View getView(int position, View convertView, ViewGroup parent) {

View view = null;

if (convertView != null) {

view = convertView;

populate(view, getItem(position));

...

} else {

view = new Xxx(...);

...

}

return view;

}

(三) Bitmap对象不在使用时调用recycle()释放内存

描述:

有时我们会手工的操作Bitmap对象,如果一个Bitmap对象比较占内存,当它不在被使用的时候,可以调用Bitmap.recycle()方法回收此对象的像素所占用的内存,但这不是必须的,视情况而定。可以看一下代码中的注释:

/**

* Free up the memory associated with this bitmap's pixels, and mark the

* bitmap as "dead", meaning it will throw an exception if getPixels() or

* setPixels() is called, and will draw nothing. This operation cannot be

* reversed, so it should only be called if you are sure there are no

* further uses for the bitmap. This is an advanced call, and normally need

* not be called, since the normal GC process will free up this memory when

* there are no more references to this bitmap.

*/

(四) 释放对象的引用

描述:

这种情况描述起来比较麻烦,举两个例子进行说明。

示例A:

假设有如下操作

public class DemoActivity extends Activity {

... ...

private Handler mHandler = ...

private Object obj;

public void operation() {

obj = initObj();

...

[Mark]

mHandler.post(new Runnable() {

public void run() {

useObj(obj);

}

});

}

}

我们有一个成员变量 obj,在operation()中我们希望能够将处理obj实例的操作post到某个线程的MessageQueue中。在以上的代码中,即便是mHandler所在的线程使用完了obj所引用的对象,但这个对象仍然不会被垃圾回收掉,因为DemoActivity.obj还保有这个对象的引用。所以如果在DemoActivity中不再使用这个对象了,可以在[Mark]的位置释放对象的引用,而代码可以修改为:

... ...

public void operation() {

obj = initObj();

...

final Object o = obj;

obj = null;

mHandler.post(new Runnable() {

public void run() {

useObj(o);

}

}

}

... ...

示例B:

假设我们希望在锁屏界面(LockScreen)中,监听系统中的电话服务以获取一些信息(如信号强度等),则可以在LockScreen中定义一个PhoneStateListener的对象,同时将它注册到TelephonyManager服务中。对于LockScreen对象,当需要显示锁屏界面的时候就会创建一个LockScreen对象,而当锁屏界面消失的时候LockScreen对象就会被释放掉。

但是如果在释放LockScreen对象的时候忘记取消我们之前注册的PhoneStateListener对象,则会导致LockScreen无法被垃圾回收。如果不断的使锁屏界面显示和消失,则最终会由于大量的LockScreen对象没有办法被回收而引起OutOfMemory,使得system_process进程挂掉。

总之当一个生命周期较短的对象A,被一个生命周期较长的对象B保有其引用的情况下,在A的生命周期结束时,要在B中清除掉对A的引用。

(五) 其他

Android应用程序中最典型的需要注意释放资源的情况是在Activity的生命周期中,在onPause()、onStop()、onDestroy()方法中需要适当的释放资源的情况。由于此情况很基础,在此不详细说明,具体可以查看官方文档对Activity生命周期的介绍,以明确何时应该释放哪些资源

android 内存优化 性能优化的更多相关文章

  1. 转——Android应用开发性能优化完全分析

    [工匠若水 http://blog.csdn.net/yanbober 转载请注明出处.] 1 背景 其实有点不想写这篇文章的,但是又想写,有些矛盾.不想写的原因是随便上网一搜一堆关于性能的建议,感觉 ...

  2. Android 应用开发性能优化完全分析

    1 背景 其实有点不想写这篇文章的,但是又想写,有些矛盾.不想写的原因是随便上网一搜一堆关于性能的建议,感觉大家你一总结.我一总结的都说到了很多优化注意事项,但是看过这些文章后大多数存在一个问题就是只 ...

  3. 【转】Android应用开发性能优化完全分析

    http://blog.csdn.net/yanbober/article/details/48394201 1 背景 其实有点不想写这篇文章的,但是又想写,有些矛盾.不想写的原因是随便上网一搜一堆关 ...

  4. Android应用开发性能优化完全分析

    1 背景 其实有点不想写这篇文章的,但是又想写,有些矛盾.不想写的原因是随便上网一搜一堆关于性能的建议,感觉大家你一总结.我一总结的都说到了很多优化注意事项,但是看过这些文章后大多数存在一个问题就是只 ...

  5. ym——Android之ListView性能优化

    转载请注明本文出自Cym的博客(http://blog.csdn.net/cym492224103),谢谢支持! Android之ListView性能优化 假设有看过我写过的15k面试题的朋友们一定知 ...

  6. 转:Android应用开发性能优化完全分析

    转自:http://blog.csdn.net/yanbober/article/details/48394201 1 背景 其实有点不想写这篇文章的,但是又想写,有些矛盾.不想写的原因是随便上网一搜 ...

  7. 利用 gperftools 对nginx mysql 内存管理 性能优化

    利用 gperftools 对nginx 与 mysql  进行 内存管理  性能优化 降低负载. Gperftools 是由谷歌开发.官方对gperftools 的介绍为: These tools ...

  8. <只看这个就够了。。。>Android自动化测试及性能优化

    Android自动化测试及性能优化 分类: Android Java Tools2012-12-09 23:31 4300人阅读 评论(0) 收藏 举报 软件自动化测试对于程序员来说能够确保软件开发的 ...

  9. Android异常与性能优化相关面试问题-内存管理面试问题详解

    内存管理机制概述: 分配机制:操作系统会为每一个进程分配一个合理的内存大小,从而保证每一个进程能够正常的运行,不至于内存不够使用,或者某个进程占用过多的内存. 回收机制:在系统内存不足的时候,系统有一 ...

随机推荐

  1. [D3] Modify DOM Elements with D3 v4

    Once you can get hold of DOM elements you’re ready to start changing them. Whether it’s changing col ...

  2. 使用docker 搭建基础的 mysql 应用

    mysql server是眼下比較流行的开源数据库server.以下介绍怎样使用docker来做一个mysql数据库服务 从站点直接 pull 一个 mysql 的镜像 core@localhost ...

  3. php课程 10-34 目录遍历中的注意事项是什么

    php课程 10-34 目录遍历中的注意事项是什么 一.总结 一句话总结:用scandir,会把目录和文件放到一个数组中. 1.移动文件怎么实现,php里面没有移动文件这个函数? 先复制,再删除 2 ...

  4. android 指定时间加一个小时算法

    import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; public class My ...

  5. [AngularFire 2] Object Observables - How to Read Objects from a Firebase Database?

    In this lesson we are going to learn how to use AngularFire 2 to query objects, and read them from t ...

  6. Ubuntu下成功安装QQ2013

    阳光小强最近用Win8系统感觉特别不爽,中午果断换了一个win7系统,又想着能不能搞个双系统(最近在看一些linux东西),于是就开始整起来.结果并不好,linux虽然整好了,但是硬盘全部格式化了,当 ...

  7. 是男人就下100层【第四层】——Crazy贪吃蛇(3)

    上一篇<是男人就下100层[第四层]--Crazy贪吃蛇(2)>实现了贪吃蛇绕着屏幕四周移动,这一篇我们来完成贪吃蛇的所有功能. 一.随机产生苹果 private void addAppl ...

  8. thinkphp3.2二维码扩展

    //简易二维码 public function qrcode(){ Vendor('phpqrcode.phpqrcode'); //生成二维码图片 $object = new \QRcode(); ...

  9. 【u106】3D模型

    Time Limit: 1 second Memory Limit: 128 MB [问题描述] 一座城市建立在规则的n×m网格上,并且网格均由1×1正方形构成.在每个网格上都可以有一个建筑,建筑由若 ...

  10. javascript中定义事件的三种方式 分类: C1_HTML/JS/JQUERY 2014-08-07 10:27 634人阅读 评论(0) 收藏

    在javascript中,可以为某个元素指定事件,指定的方式有以下三种: 1.在html中,使用onclick属性 2.在javascript中,使用onclick属性 3.在javascipt中,使 ...