当前位置: 首页 > news >正文

给县里做网站google官网进入

给县里做网站,google官网进入,深圳营销型网站推广,京东做代码的网站https://blog.csdn.net/huachao1001/article/details/52197729 我们经常会在不经意间写出造成内存泄漏的代码,往往在代码上很难查出来。但是我们可以通过一些辅助工具来检测是否存在内存泄漏,比如通过AndroidStudio的monitors来查看内存的变化情况&#…

 https://blog.csdn.net/huachao1001/article/details/52197729

我们经常会在不经意间写出造成内存泄漏的代码,往往在代码上很难查出来。但是我们可以通过一些辅助工具来检测是否存在内存泄漏,比如通过AndroidStudio的monitors来查看内存的变化情况,或者是通过开源框架《LeakCanary》来检测。本文主要是从网络中搜索汇总一些常见的内存泄漏,一方面自己应对校招,另一方面以后自己写代码时也会注意这些问题。当然了,还有一方面就是方便大家~

1 Activity对象未被回收

本节是从《Eight Ways Your Android App Can Leak Memory》中学习并总结。

1.1 静态变量引用Activity对象

通过静态变量引用Activty对象时,会导致Activty对象所占内存内漏。主要是因为,静态变量是驻扎在JVM的方法区,因此,静态变量引用的对象是不会被GC回收的,因为它们所引用的对象本身就是GC ROOT(这块不清楚的请参考我的另一篇文章《JVM理解其实并不难! 》)。即最终导致Activity对象不被回收,从而也就造成内存泄漏。

看个简单例子,比如说,你应用启动Activty的场景很多,你希望定义一个工具类Util.java,在这个类中,定义一个启动Activty的方法startActivity(Class nextActivity);以此来简化启动Activty的代码。另外,加入你当前的Activty启动另一个Activty的代码使用率也特别高。为了使得参数尽可能的少,你提供setFirstActivty,保存当前的Activty。代码如下:

Util.java

/*** Created by HuaChao on 2016/8/13.*/
public class Util {private static Activity sActivity;public static void setActivity(Activity activity) {sActivity = activity;}public static void startActivity(Class nextActivity) {Intent intent = new Intent(sActivity, nextActivity);sActivity.startActivity(intent);}
}

在当前的Activty中,只需在onCreate中调用Util.setFirstActivity(this);,在需要启动另一个Activty处调用Util.startActivity(SecondActivity.class);

在上面代码中,如果当前的Activty不再使用且Util中的sActivity对象没有更改,会导致当前Activty一直驻留在内存中。

1.2 静态View

有时,当一个Activity经常启动,但是对应的View读取非常耗时,我们可以通过静态View变量来保持对该Activity的rootView引用。这样就可以不用每次启动Activity都去读取并渲染View了。这确实是一个提高Activity启动速度的好方法!但是要注意,一旦View attach到我们的Window上,就会持有一个Context(即Activity)的引用。而我们的View有事一个静态变量,所以导致Activity不被回收。当然了,也不是说不能使用静态View,但是在使用静态View时,需要确保在资源回收时,将静态View detach掉。

1.3 内部类

我们知道,非静态内部类持有外部类的一个引用。因此,如果我们在一个外部类中定义一个静态变量,这个静态变量是引用内部类对象。将会导致内存泄漏!因为这相当于间接导致静态引用外部类。

static InnerClass innerClass;@Override
protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main); innerClass = this.new InnerClass(); 
}class InnerClass { 
}

1.4 匿名类

与内部类一样,匿名类也会持有外部类的引用。

@Override
protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);new AsyncTask<Void, Void, Void>() {@Overrideprotected Void doInBackground(Void... params) {//另一个线程中持有Activity的引用,并且不释放while (true) ;}}.execute();}

1.5 Handler

我们知道,主线程的Looper对象不断从消息队列中取出消息,然后再交给Handler处理。如果在Activity中定义Handler对象,那么Handler肯定是持有Activty的引用。而每个Message对象是持有Handler的引用的(Message对象的target属性持有Handler引用),从而导致Message间接引用到了Activity。如果在Activty destroy之后,消息队列中还有Message对象,Activty是不会被回收的。当然了,如果消息正在准备(处于延时入队期间)放入到消息队列中也是一样的。

private final Handler handler = new Handler() {@Overridepublic void handleMessage(Message msg) {}
};@Override
protected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);handler.postDelayed(new Runnable() {@Overridepublic void run() { /* ... */ }}, Integer.MAX_VALUE); 
}

解决办法就是,将Handler放入单独的类或者将Handler放入到静态内部类中(静态内部类不会持有外部类的引用)。如果想要在handler内部去调用所在的外部类Activity,可以在handler内部使用弱引用的方式指向所在Activity,这样不会导致内存泄漏。

1.6 Threads和TimerTask

Threads和Timer导致内存泄漏的原因跟内部类一样。虽然在新的线程中创建匿名类,但是只要是匿名类/内部类,它都会持有外部类引用。

void spawnThread() {new Thread() {@Override public void run() {while(true);}}.start();
}void scheduleTimer() {new Timer().schedule(new TimerTask() {@Overridepublic void run() {while(true);}}, Long.MAX_VALUE >> 1);
}

1.7 监听器

当我们需要使用系统服务时,比如执行某些后台任务、为硬件访问提供接口等等系统服务。我们需要把自己注册到服务的监听器中。然而,这会让服务持有 activity 的引用,如果程序员忘记在 activity 销毁时取消注册,那就会导致 activity 泄漏了。

void registerListener() {SensorManager sensorManager = (SensorManager) getSystemService(SENSOR_SERVICE);Sensor sensor = sensorManager.getDefaultSensor(Sensor.TYPE_ALL);sensorManager.registerListener(this, sensor, SensorManager.SENSOR_DELAY_FASTEST);
}

2 集合对象造成的泄漏

当我们定义一个静态的集合类时,请注意,这可能会导致内存泄漏!前面我们提到过,静态变量所引用的对象是不会被回收掉的。而我的静态集合类中,包含有大量的对象,这些对象不会被回收。另外,如果集合中保存的对象又引用到了其他的大对象,如超长字符串、Bitmap、大数组等,很容易造成OOM。

3 资源对象没关闭造成内存泄漏

当我们打开资源时,一般都会使用缓存。比如读写文件资源、打开数据库资源、使用Bitmap资源等等。当我们不再使用时,应该关闭它们,使得缓存内存区域及时回收。虽然有些对象,如果我们不去关闭,它自己在finalize()函数中会自行关闭。但是这得等到GC回收时才关闭,这样会导致缓存驻留一段时间。如果我们频繁的打开资源,内存泄漏带来的影响就比较明显了。

4 使用对象池避免频繁创建对象

在我们需要频繁创建使用某个类时,或者是在for循环里面创建新的对象时,导致JVM不断创建同一个类。我们知道,在使用Message对象时,不是直接new出来的,而是通过obtain方法获取,以及recycle方法回收。这是典型的享元模式(不熟悉的同学参考《从Android代码中来记忆23种设计模式 》)。我们可以通过使用对象池来实现.

import android.support.v4.util.Pools;/*** Created by HuaChao on 2016/8/13.*/
public class MyObject {private static final Pools.SynchronizedPool<MyObject> MY_POOLS = new Pools.SynchronizedPool<>(10);public static MyObject obtain() {MyObject object = MY_POOLS.acquire();if (object == null)object = new MyObject();return object;}public void recycle() {MY_POOLS.release(this);}
}
http://www.lbrq.cn/news/2797345.html

相关文章:

  • 张家港手机网站建设郑州网站策划
  • 小额贷款 网站模板seo优化是怎么优化的
  • 微商做色情网站全世界足球排名前十位
  • 做网站负责人有法律风险吗广告营销案例分析
  • 政府网站建设方案范文—工作方案google关键词搜索技巧
  • WordPress主题Perimg优化培训课程
  • 本溪网站建设百度网址提交
  • 接单网站设计 只做设计图报价千锋教育的口碑怎么样
  • 中国建设银行山西分行招聘网站企业全网推广公司
  • 珠海企业集团网站建设网络营销策划是什么
  • 网站建设与推广策划案案例优化人员是什么意思
  • 松桃县住房和城乡建设局网站网站应该如何进行优化
  • 一个女的让我和她做优惠网站策划推广
  • 西安公司网站费用百度seo插件
  • wordpress过FTP更新建站合肥网络公司seo
  • 装饰公司看的设计网站百度客户端官网
  • 班级网站开发报告seo推广外包报价表
  • 彭阳县城乡与住房建设局网站搜狗站长工具
  • 哪个网站简历做的好淘大象排名查询
  • 网店托管公司seo网络营销
  • 关键词排名优化提升培训百度竞价优化
  • 汉化主题做网站效果图强力搜索引擎
  • 事业单位网站建设方案关键词提取工具
  • 做知乎网站的图片东莞seo整站优化火速
  • 商城网站建设合同烟台seo网络推广
  • 广西网站建设介绍百度seo通科
  • 网站建设自己怎么做最强大的搜索引擎
  • 四川建设厅官方网站查询网站推广优化外包公司哪家好
  • 网站世界排名怎么做谁有恶意点击软件
  • 做外贸哪些b2b网站比较有效重庆seo技术教程博客
  • Effective C++ 条款54:熟悉标准库
  • 日语学习-日语知识点小记-构建基础-JLPT-N3阶段(18):文法+单词第6回1
  • Qt二维码生成器项目开发教程 - 从零开始构建专业级QR码生成工具
  • ODDR实现多bit单边沿采样数据转为多bit双沿采样数据
  • Elasticsearch Ruby 客户端elasticsearch / elasticsearch-api
  • 两台电脑之间如何传输大文件?